X-Git-Url: http://git.euphorik.ch/?p=master-thesis.git;a=blobdiff_plain;f=Parasitemia%2FParasitemia%2FGUI%2FAnalysis.fs;h=ccca1b45d9315c70c0af36f27f8b71dfe2f258c4;hp=acb9ce243f198f3156cda1025dd966e410a4cfcd;hb=ee562c3b613791fd89a5c322546229e9d364cafb;hpb=4147bfad3c85dcf4fe7d291abf7d356379d88b4f diff --git a/Parasitemia/Parasitemia/GUI/Analysis.fs b/Parasitemia/Parasitemia/GUI/Analysis.fs index acb9ce2..ccca1b4 100644 --- a/Parasitemia/Parasitemia/GUI/Analysis.fs +++ b/Parasitemia/Parasitemia/GUI/Analysis.fs @@ -1,15 +1,23 @@ module Parasitemia.GUI.Analysis open System +open System.IO +open System.Linq open System.Windows open System.Windows.Media open System.Windows.Markup open System.Windows.Shapes open System.Windows.Controls +open System.Diagnostics +open Microsoft.Win32 // For the common dialogs. +open Emgu.CV.WPF + +open UnitsOfMeasure open Config +open Types -let showWindow (parent: Window) (state: State.State) (defaultConfig: Config) : bool = +let showWindow (parent: Window) (state: State.State) : bool = let window = Views.AnalysisWindow() window.Root.Owner <- parent window.Root.Left <- parent.Left + parent.ActualWidth / 2. - window.Root.Width / 2. @@ -21,6 +29,7 @@ let showWindow (parent: Window) (state: State.State) (defaultConfig: Config) : b let butClose: Button = ctrl "butClose" let butStart: Button = ctrl "butStart" + let stackImagesSourceSelection: StackPanel = ctrl "stackImagesSourceSelection" let progressBar: ProgressBar = ctrl "progress" let textLog: TextBlock = ctrl "textLog" let scrollLog: ScrollViewer = ctrl "scrollLog" @@ -30,36 +39,94 @@ let showWindow (parent: Window) (state: State.State) (defaultConfig: Config) : b textLog.Inlines.Add(Documents.LineBreak()) scrollLog.ScrollToBottom())) + let minPPI = 1. + let maxPPI = 10e6 + let parseAndValidatePPI (input: string) : float option = + let res = ref 0. + if Double.TryParse(input, res) && !res >= minPPI && !res <= maxPPI + then Some !res + else None + let monitor = Object() + let mutable atLeastOneAnalysisPerformed = false let mutable analysisPerformed = false let mutable analysisCancelled = false + let updateSourceImages () = + stackImagesSourceSelection.Children.Clear() + let width = int stackImagesSourceSelection.ActualWidth + for srcImg in state.SourceImages do + let imageSourceSelection = Views.ImageSourceSelection(Tag = srcImg, Margin = Thickness(3.)) + + let updateResolution () = + match parseAndValidatePPI imageSourceSelection.txtResolution.Text with + | Some resolution -> srcImg.config.Parameters <- { srcImg.config.Parameters with resolution = resolution * 1. } + | None -> () + + imageSourceSelection.txtImageNumber.Text <- srcImg.num.ToString() + let height = srcImg.img.Height * width / srcImg.img.Width + imageSourceSelection.imagePreview.Source <- BitmapSourceConvert.ToBitmapSource(srcImg.img.Resize(width, height, Emgu.CV.CvEnum.Inter.Cubic)) + imageSourceSelection.chkSelection.IsChecked <- Nullable(srcImg.dateLastAnalysis.Ticks = 0L) + imageSourceSelection.lblDateLastAnalysis.Content <- if srcImg.dateLastAnalysis.Ticks = 0L then "" else srcImg.dateLastAnalysis.ToString() + + imageSourceSelection.txtResolution.Text <- srcImg.config.Parameters.resolution.ToString() + imageSourceSelection.menuZoom50X.Click.AddHandler(fun obj args -> imageSourceSelection.txtResolution.Text <- "200000"; updateResolution ()) + imageSourceSelection.menuZoom100X.Click.AddHandler(fun obj args -> imageSourceSelection.txtResolution.Text <- "400000"; updateResolution ()) + + imageSourceSelection.txtResolution.PreviewTextInput.AddHandler(fun obj args -> + let text = imageSourceSelection.txtResolution.Text + args.Text + args.Handled <- match parseAndValidatePPI text with Some _ -> false | None -> true) + + imageSourceSelection.imagePreview.MouseLeftButtonDown.AddHandler(fun obj args -> + let checkbox = imageSourceSelection.chkSelection + checkbox.IsChecked <- Nullable(not (checkbox.IsChecked.HasValue && checkbox.IsChecked.Value))) + + imageSourceSelection.txtResolution.LostFocus.AddHandler(fun obj args -> updateResolution ()) + + stackImagesSourceSelection.Children.Add(imageSourceSelection) |> ignore + 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) + let imagesToProcess = [ + for imageSelection in stackImagesSourceSelection.Children |> Seq.cast do + let chk = imageSelection.chkSelection.IsChecked + if chk.HasValue && chk.Value + then + let srcImg = imageSelection.Tag :?> SourceImage + yield srcImg.num.ToString(), srcImg.config, srcImg.img ] + + if imagesToProcess.IsEmpty + then + MessageBox.Show("No image selected", "Cannot start analysis", MessageBoxButton.OK, MessageBoxImage.Information) |> ignore + else + analysisPerformed <- false + butStart.IsEnabled <- false + butClose.Content <- "Abort" + async { + let results = + ImageAnalysis.doMultipleAnalysis + imagesToProcess + (Some (fun progress -> window.Root.Dispatcher.Invoke(fun () -> progressBar.Value <- float progress))) + + lock monitor ( + fun() -> + if not analysisCancelled + then + for id, cells in results do + state.SetResult (int id) cells + + window.Root.Dispatcher.Invoke(fun () -> + butStart.IsEnabled <- true + butClose.Content <- "Close" + updateSourceImages ()) + + Utils.log "Analysis terminated successfully" + atLeastOneAnalysisPerformed <- true + analysisPerformed <- true) + } |> Async.Start) + + window.Root.Loaded.AddHandler(fun obj args -> updateSourceImages ()) window.Root.ShowDialog() |> ignore @@ -67,7 +134,7 @@ let showWindow (parent: Window) (state: State.State) (defaultConfig: Config) : b if not analysisPerformed then analysisCancelled <- true - analysisPerformed) + atLeastOneAnalysisPerformed) (*let results = ImageAnalysis.doMultipleAnalysis (state.SourceImages |> Seq.map (fun srcImg -> string srcImg.num, srcImg.img) |> Seq.toList) defaultConfig