module Parasitemia.Main open System open System.IO open System.Windows open System.Windows.Media open System.Windows.Markup open System.Windows.Shapes open System.Windows.Controls open System.Drawing open System.Diagnostics open Emgu.CV open Emgu.CV.Structure open Emgu.CV.WPF open Config let display (window : Views.MainWindow) (img : IImage) = let imgControl = window.Root.FindName("img") :?> Controls.Image imgControl.Source <- BitmapSourceConvert.ToBitmapSource(img) let log (window : Views.MainWindow) (mess : string) = let txtLog = window.Root.FindName("txtLog") :?> Controls.TextBlock txtLog.Text <- txtLog.Text + mess + "\n" type Input = | File of string | Dir of string type RunningMode = | CmdLine of Input * string | Window type Arguments = RunningMode * bool let parseArgs (args: string[]) : Arguments = let output = Array.tryFindIndex ((=) "--output") args let runningMode = match Array.tryFindIndex ((=) "--folder") args, output with | Some i, Some i_output when i < args.Length - 2 && i_output < args.Length - 2 -> CmdLine ((Dir args.[i+1]), args.[i_output + 1]) | _ -> match Array.tryFindIndex ((=) "--file") args, output with | Some i, Some i_output when i < args.Length - 2 && i_output < args.Length - 2 -> CmdLine ((File args.[i+1]), args.[i_output + 1]) |_ -> Window runningMode, Array.exists ((=) "--debug") args [] let main args = match parseArgs args with | mode, debug -> let config = Config( { scale = 1. initialAreaOpen = 2000 minRbcRadius = -0.32 maxRbcRadius = 0.32 preFilterSigma = 1.7 // 1.5 factorNbPick = 1.0 factorWindowSize = 2.0 darkStainLevel = 0.25 // Lower -> more sensitive. 0.3 maxDarkStainRatio = 0.1 // 10 % infectionArea = 0.012 // 1.2 % infectionLevel = 1.12 // Lower -> more sensitive. stainArea = 0.08 // 8 % stainLevel = 1.1 // Lower -> more sensitive. maxStainRatio = 0.12 // 12 % standardDeviationMaxRatio = 0.5 // 0.55 minimumCellArea = 0.5 }) match mode with | CmdLine (input, output) -> if debug then config.Debug <- DebugOn output Directory.CreateDirectory output |> ignore use logFile = new StreamWriter(new FileStream(Path.Combine(output, "log.txt"), FileMode.Append, FileAccess.Write)) Utils.log <- (fun m -> logFile.WriteLine(m)) Utils.log (sprintf "=== New run : %A %A ===" DateTime.Now (if debug then "[DEBUG]" else "[RELEASE]")) let files = match input with | File file -> [ file ] | Dir dir -> Directory.EnumerateFiles dir |> List.ofSeq use resultFile = new StreamWriter(new FileStream(Path.Combine(output, "results.txt"), FileMode.Append, FileAccess.Write)) for file in files do try use img = new Image(file) Utils.log (sprintf "== File: %A" file) let cells = Utils.logTime "Whole analyze" (fun () -> ImageAnalysis.doAnalysis img (Path.GetFileNameWithoutExtension(FileInfo(file).Name)) config) let total, infected = Utils.countCells cells fprintf resultFile "File: %s %d %d %.2f\n" file total infected (100. * (float infected) / (float total)) with | :? IOException as ex -> Utils.log (sprintf "Unable to open the image '%A': %A" file ex) 0 | Window -> let app = new Application() let mainWindow = Views.MainWindow() if debug then config.Debug <- DebugOn "." Utils.log <- (fun m -> log mainWindow m) //display mainWindow img mainWindow.Root.Show() app.Run()