* Try another approach to remove false ellipses without success (commented).
[master-thesis.git] / Parasitemia / Parasitemia / Classifier.fs
index f0c9d01..341f7c9 100644 (file)
@@ -103,10 +103,8 @@ let findCells (ellipses: Ellipse list) (parasites: ParasitesMarker.Result) (img:
             if e.isOutside w_f h_f then e.Removed <- true
 
         // 3) Remove ellipses with a high standard deviation (high contrast).
-
-        // CvInvoke.Normalize(img, img, 0.0, 255.0, CvEnum.NormType.MinMax) // Not needed.
         let imgData = img.Data
-        let globalStdDeviation = MathNet.Numerics.Statistics.Statistics.StandardDeviation(seq {
+        let globalStdDeviation = MathNet.Numerics.Statistics.Statistics.PopulationStandardDeviation(seq {
             for y in 0 .. h - 1 do
                 for x in 0 .. w - 1 do
                     yield float imgData.[y, x, 0] })
@@ -127,6 +125,40 @@ let findCells (ellipses: Ellipse list) (parasites: ParasitesMarker.Result) (img:
                 if stdDeviation > globalStdDeviation * config.Parameters.standardDeviationMaxRatio then
                     e.Removed <- true
 
+(*
+        let imgData = img.Data
+                let stdDeviations = [
+                    for e in ellipses do
+                        if not e.Removed
+                        then
+                            let shrinkedE = e.Scale 0.9f
+                            let minX, minY, maxX, maxY = ellipseWindow shrinkedE
+
+                            let stdDeviation = float32 <| MathNet.Numerics.Statistics.Statistics.StandardDeviation (seq {
+                                for y in (if minY < 0 then 0 else minY) .. (if maxY >= h then h - 1 else maxY) do
+                                    for x in (if minX < 0 then 0 else minX) .. (if maxX >= w then w - 1 else maxX) do
+                                        if shrinkedE.Contains (float32 x) (float32 y)
+                                        then
+                                            yield float imgData.[y, x, 0] })
+
+                            e.StdDeviation <- stdDeviation
+                            yield stdDeviation ]
+
+                // We use Otsu and eliminate some cells only if the curve may be bimodal.
+                // See https://en.wikipedia.org/wiki/Multimodal_distribution#Bimodality_coefficient
+                let skewness, kurtosis = MathNet.Numerics.Statistics.Statistics.PopulationSkewnessKurtosis (stdDeviations |> List.map float)
+                let n = float stdDeviations.Length
+                let bimodalityCoefficient = (skewness ** 2. + 1.) / (kurtosis + 3. * (n - 1.) ** 2. / ((n - 2.) * (n - 3.)))
+
+                if bimodalityCoefficient > 5. / 9.
+                then
+                    let hist = ImgTools.histogram stdDeviations 200
+                    let thresh, _, _ = ImgTools.otsu hist
+                    for e in ellipses do
+                        if not e.Removed && e.StdDeviation > thresh
+                        then e.Removed <- true
+*)
+
         // 4) Remove ellipses with little area.
         let minArea = config.RBCMinArea
         for e, neighbors in ellipsesWithNeigbors do