Use float32 to reduce memory footprint.
[master-thesis.git] / Parasitemia / Parasitemia / Program.fs
1 module Parasitemia.Main
2
3 open System
4 open System.IO
5 open System.Windows
6 open System.Windows.Media
7 open System.Windows.Markup
8 open System.Windows.Shapes
9 open System.Windows.Controls
10 open System.Drawing
11 open System.Diagnostics
12 open System.Threading
13
14 open FSharp.Collections.ParallelSeq
15
16 open Emgu.CV
17 open Emgu.CV.Structure
18 open Emgu.CV.WPF
19
20 open Config
21
22 let display (window : Views.MainWindow) (img : IImage) =
23 let imgControl = window.Root.FindName("img") :?> Controls.Image
24 imgControl.Source <- BitmapSourceConvert.ToBitmapSource(img)
25
26 let log (window : Views.MainWindow) (mess : string) =
27 let txtLog = window.Root.FindName("txtLog") :?> Controls.TextBlock
28 txtLog.Text <- txtLog.Text + mess + "\n"
29
30
31 type Input =
32 | File of string
33 | Dir of string
34
35 type RunningMode =
36 | CmdLine of Input * string
37 | Window
38
39 type Arguments = RunningMode * bool
40
41 let parseArgs (args: string[]) : Arguments =
42
43 let output = Array.tryFindIndex ((=) "--output") args
44
45 let runningMode =
46 match Array.tryFindIndex ((=) "--folder") args, output with
47 | Some i, Some i_output when i < args.Length - 2 && i_output < args.Length - 2 ->
48 CmdLine ((Dir args.[i+1]), args.[i_output + 1])
49 | _ ->
50 match Array.tryFindIndex ((=) "--file") args, output with
51 | Some i, Some i_output when i < args.Length - 2 && i_output < args.Length - 2 ->
52 CmdLine ((File args.[i+1]), args.[i_output + 1])
53 |_ ->
54 Window
55
56 runningMode, Array.exists ((=) "--debug") args
57
58
59 [<EntryPoint>]
60 let main args =
61 match parseArgs args with
62 | mode, debug ->
63 let config =
64 Config(
65 { scale = 1.
66
67 initialAreaOpen = 2000
68
69 minRbcRadius = -0.32f
70 maxRbcRadius = 0.32f
71
72 preFilterSigma = 1.7 // 1.5
73
74 factorNbPick = 1.0
75
76 darkStainLevel = 0.22 // Lower -> more sensitive. 0.3. Careful about illumination on the borders.
77 maxDarkStainRatio = 0.1 // 10 %
78
79 infectionArea = 0.012f // 1.2 %
80 infectionLevel = 1.12 // Lower -> more sensitive.
81
82 stainArea = 0.08f // 8 %
83 stainLevel = 1.1 // Lower -> more sensitive.
84 maxStainRatio = 0.12 // 12 %
85
86 standardDeviationMaxRatio = 0.5 // 0.55
87 minimumCellArea = 0.5f })
88
89 match mode with
90 | CmdLine (input, output) ->
91 if debug
92 then
93 config.Debug <- DebugOn output
94
95 Directory.CreateDirectory output |> ignore
96
97 use logFile = new StreamWriter(new FileStream(Path.Combine(output, "log.txt"), FileMode.Append, FileAccess.Write))
98 Utils.log <- (fun m -> logFile.WriteLine(m))
99 Utils.log (sprintf "=== New run : %A %A ===" DateTime.Now (if debug then "[DEBUG]" else "[RELEASE]"))
100
101 let files = match input with
102 | File file -> [ file ]
103 | Dir dir -> Directory.EnumerateFiles dir |> List.ofSeq
104
105 use resultFile = new StreamWriter(new FileStream(Path.Combine(output, "results.txt"), FileMode.Append, FileAccess.Write))
106
107 //try
108 let images = seq { for file in files -> Path.GetFileNameWithoutExtension(FileInfo(file).Name), new Image<Bgr, byte>(file) }
109
110 let nbConcurrentTaskLimit = 4
111 let n = Environment.ProcessorCount
112
113 Utils.logTime "Whole analyze" (fun () ->
114 let results =
115 images
116 |> PSeq.map (fun (id, img) -> id, ImageAnalysis.doAnalysis img id (config.Copy()))
117 |> PSeq.withDegreeOfParallelism (if n > nbConcurrentTaskLimit then nbConcurrentTaskLimit else n)
118
119 for id, cells in results do
120 let total, infected = Utils.countCells cells
121 fprintf resultFile "File: %s %d %d %.2f\n" id total infected (100. * (float infected) / (float total)))
122
123 //Utils.log (sprintf "== File: %A" file)
124 //with
125 //| :? IOException as ex -> Utils.log (sprintf "Unable to open the image '%A': %A" file ex)
126 0
127
128 | Window ->
129 let app = new Application()
130 let mainWindow = Views.MainWindow()
131
132 if debug
133 then
134 config.Debug <- DebugOn "."
135
136 Utils.log <- (fun m -> log mainWindow m)
137
138 //display mainWindow img
139 mainWindow.Root.Show()
140 app.Run()