Cleaning.
authorGreg Burri <greg.burri@gmail.com>
Tue, 22 Dec 2015 00:38:04 +0000 (01:38 +0100)
committerGreg Burri <greg.burri@gmail.com>
Tue, 22 Dec 2015 00:38:04 +0000 (01:38 +0100)
Parasitemia/Parasitemia/Classifier.fs
Parasitemia/Parasitemia/Config.fs
Parasitemia/Parasitemia/Ellipse.fs
Parasitemia/Parasitemia/MainAnalysis.fs
Parasitemia/Parasitemia/ParasitesMarker2.fs
Parasitemia/Parasitemia/Program.fs
Parasitemia/Parasitemia/Types.fs

index 4c6cc56..a12e595 100644 (file)
@@ -29,10 +29,10 @@ let findCells (ellipses: Ellipse list) (parasites: ParasitesMarker2.Result) (img
         let infection = parasites.infection.Copy() // To avoid to modify the parameter.
 
         // This is the minimum window size to check if other ellipses touch 'e'.
-        let searchRegion (e: Ellipse) = { KdTree.minX = e.Cx - (e.A + config.RBCMax) * config.Parameters.scale
-                                          KdTree.maxX = e.Cx + (e.A + config.RBCMax) * config.Parameters.scale
-                                          KdTree.minY = e.Cy - (e.A + config.RBCMax) * config.Parameters.scale
-                                          KdTree.maxY = e.Cy + (e.A + config.RBCMax) * config.Parameters.scale }
+        let searchRegion (e: Ellipse) = { KdTree.minX = e.Cx - (e.A + config.RBCMaxRadius) * config.Parameters.scale
+                                          KdTree.maxX = e.Cx + (e.A + config.RBCMaxRadius) * config.Parameters.scale
+                                          KdTree.minY = e.Cy - (e.A + config.RBCMaxRadius) * config.Parameters.scale
+                                          KdTree.maxY = e.Cy + (e.A + config.RBCMaxRadius) * config.Parameters.scale }
 
         // The minimum window to contain a given ellipse.
         let ellipseWindow (e: Ellipse) =
@@ -114,8 +114,12 @@ let findCells (ellipses: Ellipse list) (parasites: ParasitesMarker2.Result) (img
                 let c = PointD(e.Cx, e.Cy)
                 for d1 in lines do
                     let d2 = Utils.lineFromTwoPoints c p
-                    let p' = Utils.pointFromTwoLines d1 d2
-                    yield sign (c.X - p.X) <> sign (c.X - p'.X) || Utils.squaredDistanceTwoPoints c p' > Utils.squaredDistanceTwoPoints c p // 'false' -> the point is owned by another ellipse.
+                    if d2.Valid
+                    then
+                        let p' = Utils.pointFromTwoLines d1 d2
+                        yield sign (c.X - p.X) <> sign (c.X - p'.X) || Utils.squaredDistanceTwoPoints c p' > Utils.squaredDistanceTwoPoints c p // 'false' -> the point is owned by another ellipse.
+                    else
+                        yield true
             } |> Seq.forall id
 
         ellipsesWithNeigbors
@@ -171,7 +175,7 @@ let findCells (ellipses: Ellipse list) (parasites: ParasitesMarker2.Result) (img
                         sqrt (((float sumCoords_x) / (float nbElement) - e.Cx) ** 2.0 + ((float sumCoords_y) / (float nbElement) - e.Cy) ** 2.0) > e.A * config.maxOffcenter *)
                     then
                         Peculiar
-                    elif infectedPixels.Count > config.Parameters.infectionPixelsRequired
+                    elif infectedPixels.Count > config.Parameters.parasitePixelsRequired
                     then
                         let infectionToRemove = ImgTools.connectedComponents parasites.stain infectedPixels
                         for p in infectionToRemove do
index 55e142c..a1b06e2 100644 (file)
@@ -26,7 +26,7 @@ type Parameters = {
 
     infectionArea: float // Factor of a RBC area. 0.5 means the half of RBC area.
     infectionLevel: float // [0, 1]
-    infectionPixelsRequired: int
+    parasitePixelsRequired: int
 
     maxDarkStainRatio: float
 
@@ -36,12 +36,12 @@ type Parameters = {
 type Config (param: Parameters) =
     member this.Parameters = param
     member val Debug = DebugOff with get, set
-    member val RBCSize = 30. with get, set
+    member val RBCRadius = 30. with get, set
 
-    member this.RBCMin = this.RBCSize + param.minRbcRadius * this.RBCSize
-    member this.RBCMax = this.RBCSize + param.maxRbcRadius * this.RBCSize
+    member this.RBCMinRadius = this.RBCRadius + param.minRbcRadius * this.RBCRadius
+    member this.RBCMaxRadius = this.RBCRadius + param.maxRbcRadius * this.RBCRadius
 
-    member this.RBCMinArea = param.minimumCellArea * Math.PI * this.RBCSize ** 2.0
+    member this.RBCMinArea = param.minimumCellArea * Math.PI * this.RBCRadius ** 2.0
 
-    member this.ParasiteArea = param.infectionArea * Math.PI * this.RBCSize ** 2.0
-    member this.StainArea = param.stainArea * Math.PI * this.RBCSize ** 2.0
+    member this.InfectionArea = param.infectionArea * Math.PI * this.RBCRadius ** 2.0
+    member this.StainArea = param.stainArea * Math.PI * this.RBCRadius ** 2.0
index 33333bf..48c7f54 100644 (file)
@@ -208,7 +208,7 @@ let find (edges: Matrix<byte>)
          (yDir: Image<Gray, float>)
          (config: Config) : MatchingEllipses =
 
-    let r1, r2 = config.Parameters.scale * config.RBCMin, config.Parameters.scale * config.RBCMax // FIXME: scale factor should be applied in Config!?
+    let r1, r2 = config.Parameters.scale * config.RBCMinRadius, config.Parameters.scale * config.RBCMaxRadius // FIXME: scale factor should be applied in Config!?
     let windowSize = roundInt (config.Parameters.factorWindowSize * r2)
     let factorNbPick = config.Parameters.factorNbPick
 
index d959624..6f78b7c 100644 (file)
@@ -32,22 +32,23 @@ let doAnalysis (img: Image<Bgr, byte>) (name: string) (config: Config) : Cell li
 
     logTime "areaOpen" (fun () -> ImgTools.areaOpen filteredGreen 2000)
 
-    config.RBCSize <- Granulometry.findRadius filteredGreen (10, 100) 0.5 |> float
+    config.RBCRadius <- Granulometry.findRadius filteredGreen (10, 100) 0.5 |> float
 
     let filteredGreenFloat = filteredGreen.Convert<Gray, float32>() // Is it neccessary?
 
     let kmediansResults = logTime "Finding foreground (k-medians)" (fun () -> KMedians.kmedians filteredGreenFloat 1.0)
 
-    let parasites, filteredGreenWhitoutParasites, filteredGreenWhitoutStain = ParasitesMarker2.find filteredGreen filteredGreenFloat kmediansResults config
-    let filteredGreenWhitoutParasitesFloat = filteredGreenWhitoutParasites.Convert<Gray, float32>()
+    let parasites, filteredGreenWhitoutInfection, filteredGreenWhitoutStain = ParasitesMarker2.find filteredGreen filteredGreenFloat kmediansResults config
+    let filteredGreenWhitoutInfectionFloat = filteredGreenWhitoutInfection.Convert<Gray, float32>()
+    let filteredGreenWhitoutStainFloat = filteredGreenWhitoutStain.Convert<Gray, float32>()
 
     use sobelKernel =
         new ConvolutionKernelF(array2D [[ 1.0f; 0.0f; -1.0f ]
                                         [ 2.0f; 0.0f; -2.0f ]
                                         [ 1.0f; 0.0f; -1.0f ]], Point(0, 0))
 
-    use xEdges = filteredGreenWhitoutParasitesFloat.Convolution(sobelKernel).Convert<Gray, float>()
-    use yEdges = filteredGreenWhitoutParasitesFloat.Convolution(sobelKernel.Transpose()).Convert<Gray, float>()
+    use xEdges = filteredGreenWhitoutStainFloat.Convolution(sobelKernel).Convert<Gray, float>()
+    use yEdges = filteredGreenWhitoutStainFloat.Convolution(sobelKernel.Transpose()).Convert<Gray, float>()
 
     let xEdgesData = xEdges.Data
     let yEdgesData = yEdges.Data
@@ -83,7 +84,7 @@ let doAnalysis (img: Image<Bgr, byte>) (name: string) (config: Config) : Cell li
         let matchingEllipses = Ellipse.find edges xEdges yEdges config
         matchingEllipses.Ellipses, matchingEllipses.PrunedEllipses )
 
-    let cells = logTime "Classifier" (fun () -> Classifier.findCells ellipses parasites filteredGreenWhitoutParasites config)
+    let cells = logTime "Classifier" (fun () -> Classifier.findCells ellipses parasites filteredGreenWhitoutStain config)
 
     // Output pictures if debug flag is set.
     match config.Debug with
@@ -123,7 +124,7 @@ let doAnalysis (img: Image<Bgr, byte>) (name: string) (config: Config) : Cell li
         saveImg filteredGreenMaxima (buildFileName " - filtered - maxima.png")
 
         saveImg filteredGreen (buildFileName " - filtered.png")
-        saveImg filteredGreenWhitoutParasites (buildFileName " - filtered closed.png")
+        saveImg filteredGreenWhitoutStain (buildFileName " - filtered closed.png")
 
         (*saveImg parasitesMarker (buildFileName " - parasites (area closing).png")
         saveImg stainMarker (buildFileName " - stain (area closing).png")*)
index 03af2b6..17a032d 100644 (file)
@@ -7,8 +7,8 @@ open Emgu.CV.Structure
 
 type Result = {
     darkStain: Image<Gray, byte>
-    stain: Image<Gray, byte>
-    infection: Image<Gray, byte> }
+    infection: Image<Gray, byte>
+    stain: Image<Gray, byte> }
 
 // Create three binary markers :
 // * 'Dark stain' corresponds to the colored pixel, it's independent of the size of the areas.
@@ -32,16 +32,18 @@ let find (filteredGreen: Image<Gray, byte>) (filteredGreenFloat: Image<Gray, flo
         let maxLocation = ref <| [| Point() |]
         diff.MinMax(min, max, minLocation, maxLocation)
 
-        diff._ThresholdBinary((!max).[0] * threshold |> Gray, Gray(255.))
+        let valueThreshold = if (!max).[0] * threshold < 0.1 * (median_bg - median_fg) then 0.1 * (median_bg - median_fg) else (!max).[0] * threshold
+
+        diff._ThresholdBinary(Gray(valueThreshold), Gray(255.))
         diff, closed
 
-    let parasitesMarker, filteredGreenWithoutParasites  = marker (int config.ParasiteArea) config.Parameters.infectionLevel
+    let infectionMarker, filteredGreenWithoutInfection  = marker (int config.InfectionArea) config.Parameters.infectionLevel
     let stainMarker, filteredGreenWithoutStain = marker (int config.StainArea) config.Parameters.stainLevel
 
     { darkStain = darkStain
-      stain = parasitesMarker
-      infection = stainMarker },
-    filteredGreenWithoutParasites,
+      infection = infectionMarker
+      stain = stainMarker },
+    filteredGreenWithoutInfection,
     filteredGreenWithoutStain
 
 
index 103596a..ac495b5 100644 (file)
@@ -71,12 +71,12 @@ let main args =
 
                 darkStainLevel = 0.4 // Lower -> more sensitive.
 
-                stainArea = 0.02
-                stainLevel = 0.2
-
-                infectionArea = 0.06
+                infectionArea = 0.015
                 infectionLevel = 0.2
-                infectionPixelsRequired = 1
+                parasitePixelsRequired = 1
+
+                stainArea = 0.06
+                stainLevel = 0.2
 
                 maxDarkStainRatio = 0.1
 
index 634a7b7..e27f7d0 100644 (file)
@@ -52,6 +52,7 @@ type Cell = {
 type Line (a: float, b: float) =
     member this.A = a
     member this.B = b
+    member this.Valid = not (Double.IsInfinity this.A)
 
 [<Struct>]
 type PointD (x: float, y: float) =