From 807437584bdd3d7b7b33be8282472f81f8cce606 Mon Sep 17 00:00:00 2001 From: Greg Burri Date: Wed, 13 Jan 2016 11:45:14 +0100 Subject: [PATCH] * Add the analysis window. * Other improvements. --- Parasitemia/Parasitemia/Config.fs | 21 +- Parasitemia/Parasitemia/GUI/Analysis.fs | 75 ++++++ .../Parasitemia/GUI/AnalysisWindow.xaml | 30 +++ .../Parasitemia/GUI/AnalysisWindow.xaml.fs | 6 + Parasitemia/Parasitemia/GUI/GUI.fs | 224 ++++++++++++------ .../Parasitemia/GUI/ImageSourcePreview.xaml | 12 +- Parasitemia/Parasitemia/GUI/MainWindow.xaml | 48 ++-- Parasitemia/Parasitemia/GUI/PiaZ.fs | 23 +- Parasitemia/Parasitemia/GUI/RBCFrame.xaml | 2 +- Parasitemia/Parasitemia/GUI/State.fs | 74 +++++- Parasitemia/Parasitemia/GUI/Types.fs | 12 +- Parasitemia/Parasitemia/MainAnalysis.fs | 36 ++- Parasitemia/Parasitemia/Parasitemia.fsproj | 15 +- Parasitemia/Parasitemia/ParasitesMarker.fs | 17 +- Parasitemia/Parasitemia/Program.fs | 7 +- Parasitemia/Parasitemia/Utils.fs | 2 +- Parasitemia/Parasitemia/packages.config | 4 +- Parasitemia/WPF/WPF.csproj | 2 +- 18 files changed, 455 insertions(+), 155 deletions(-) create mode 100644 Parasitemia/Parasitemia/GUI/Analysis.fs create mode 100644 Parasitemia/Parasitemia/GUI/AnalysisWindow.xaml create mode 100644 Parasitemia/Parasitemia/GUI/AnalysisWindow.xaml.fs diff --git a/Parasitemia/Parasitemia/Config.fs b/Parasitemia/Parasitemia/Config.fs index 5bb9936..e583160 100644 --- a/Parasitemia/Parasitemia/Config.fs +++ b/Parasitemia/Parasitemia/Config.fs @@ -9,41 +9,44 @@ type Debug = | DebugOn of string // Output directory. type Parameters = { - initialAreaOpen: int + initialAreaOpen: int // Area of the first initial opening to remove the central illumination of RBC. + ratioSecondAreaOpen: float32 // The area of the second opening is 'ratioSecondAreaOpen' * mean RBC area. It's applied only if greater than 'initialAreaOpen'. - minRbcRadius: float32 - maxRbcRadius: float32 + minRbcRadius: float32 // Factor of the mean RBC radius. + maxRbcRadius: float32 // Factor of the mean RBC radius. - preFilterSigma: float + preFilterSigma: float // To remove the high frequency noise. // Ellipse. - factorNbPick: float + factorNbPick: float // The number of computed ellipse per edge pixel. // Parasites detection. darkStainLevel: float // Lower -> more sensitive. Careful about illumination on the borders. - maxDarkStainRatio: float + maxDarkStainRatio: float // When a cell must own less than this ratio to be a RBC. stainArea: float32 // Factor of a RBC area. 0.5 means the half of RBC area. stainLevel: float // > 1 - maxStainRatio: float // [0, 1] + maxStainRatio: float // When a cell must own less than this ratio to be a RBC. infectionArea: float32 // Factor of a RBC area. 0.5 means the half of RBC area. infectionLevel: float // > 1 standardDeviationMaxRatio: float // The standard deviation of the pixel values of a cell can't be greater than standardDeviationMaxRatio * global standard deviation - minimumCellArea: float32 // Factor of the nominal RBC area. + minimumCellAreaFactor: float32 // Factor of the mean RBC area. } type Config (param: Parameters) = member this.Parameters = param member val Debug = DebugOff with get, set + + // Mean RBC radius. member val RBCRadius = 30.f with get, set member this.RBCMinRadius = this.RBCRadius + param.minRbcRadius * this.RBCRadius member this.RBCMaxRadius = this.RBCRadius + param.maxRbcRadius * this.RBCRadius member this.RBCArea = PI * this.RBCRadius ** 2.f - member this.RBCMinArea = param.minimumCellArea * this.RBCArea + member this.RBCMinArea = param.minimumCellAreaFactor * this.RBCArea member this.InfectionArea = param.infectionArea * this.RBCArea member this.StainArea = param.stainArea * this.RBCArea diff --git a/Parasitemia/Parasitemia/GUI/Analysis.fs b/Parasitemia/Parasitemia/GUI/Analysis.fs new file mode 100644 index 0000000..acb9ce2 --- /dev/null +++ b/Parasitemia/Parasitemia/GUI/Analysis.fs @@ -0,0 +1,75 @@ +module Parasitemia.GUI.Analysis + +open System +open System.Windows +open System.Windows.Media +open System.Windows.Markup +open System.Windows.Shapes +open System.Windows.Controls + +open Config + +let showWindow (parent: Window) (state: State.State) (defaultConfig: Config) : bool = + let window = Views.AnalysisWindow() + window.Root.Owner <- parent + window.Root.Left <- parent.Left + parent.ActualWidth / 2. - window.Root.Width / 2. + window.Root.Top <- parent.Top + parent.ActualHeight / 2. - window.Root.Height / 2. + + let ctrl (name: string): 'a = + window.Root.FindName(name) :?> 'a + + let butClose: Button = ctrl "butClose" + let butStart: Button = ctrl "butStart" + + let progressBar: ProgressBar = ctrl "progress" + let textLog: TextBlock = ctrl "textLog" + let scrollLog: ScrollViewer = ctrl "scrollLog" + + Utils.log <- (fun mess -> window.Root.Dispatcher.Invoke(fun () -> + textLog.Inlines.Add(Documents.Run(mess)) + textLog.Inlines.Add(Documents.LineBreak()) + scrollLog.ScrollToBottom())) + + let monitor = Object() + let mutable analysisPerformed = false + let mutable analysisCancelled = false + + butClose.Click.AddHandler(fun obj args -> window.Root.Close()) + + butStart.Click.AddHandler(fun obj args -> + butStart.IsEnabled <- false + butClose.Content <- "Abort" + async { + let results = + ImageAnalysis.doMultipleAnalysis + (state.SourceImages |> Seq.map (fun srcImg -> string srcImg.num, srcImg.img) |> Seq.toList) + defaultConfig + (Some (fun progress -> window.Root.Dispatcher.Invoke(fun () -> progressBar.Value <- float progress))) + + lock monitor ( + fun() -> + if not analysisCancelled + then + for id, rbcRadius, cells in results do + state.SetResult (int id) rbcRadius cells + + window.Root.Dispatcher.Invoke(fun () -> + butStart.IsEnabled <- false + butClose.Content <- "Close") + + Utils.log "Analysis terminated successfully" + analysisPerformed <- true) + } |> Async.Start) + + window.Root.ShowDialog() |> ignore + + lock monitor (fun () -> + if not analysisPerformed + then + analysisCancelled <- true + analysisPerformed) + + + (*let results = ImageAnalysis.doMultipleAnalysis (state.SourceImages |> Seq.map (fun srcImg -> string srcImg.num, srcImg.img) |> Seq.toList) defaultConfig + for id, rbcRadius, cells in results do + state.SetResult (int id) rbcRadius cells*) \ No newline at end of file diff --git a/Parasitemia/Parasitemia/GUI/AnalysisWindow.xaml b/Parasitemia/Parasitemia/GUI/AnalysisWindow.xaml new file mode 100644 index 0000000..6da0675 --- /dev/null +++ b/Parasitemia/Parasitemia/GUI/AnalysisWindow.xaml @@ -0,0 +1,30 @@ + + + + + + + + + + + + + + + + + + + + +