beginning of the classifier.
authorGreg Burri <greg.burri@gmail.com>
Fri, 11 Dec 2015 16:27:43 +0000 (17:27 +0100)
committerGreg Burri <greg.burri@gmail.com>
Fri, 11 Dec 2015 16:27:43 +0000 (17:27 +0100)
Parasitemia/Parasitemia/Classifier.fs [new file with mode: 0644]
Parasitemia/Parasitemia/EEOver.fs
Parasitemia/Parasitemia/ImageAnalysis.fs
Parasitemia/Parasitemia/MatchingEllipses.fs
Parasitemia/Parasitemia/Parasitemia.fsproj
Parasitemia/Parasitemia/ParasitesMarker.fs
Parasitemia/Parasitemia/Program.fs

diff --git a/Parasitemia/Parasitemia/Classifier.fs b/Parasitemia/Parasitemia/Classifier.fs
new file mode 100644 (file)
index 0000000..6441635
--- /dev/null
@@ -0,0 +1,18 @@
+module Classifier
+
+open System
+open System.Drawing
+
+open Emgu.CV
+open Emgu.CV.Structure
+
+
+type CellClass = HealthyRBC | InfectedRBC | Peculiar
+
+type Cell = { 
+    cellClass: CellClass
+    center: Point
+    elements: Matrix<byte> }
+
+let findCells (ellipses: Types.Ellipse list) (parasites: ParasitesMarker.Result) (fg: Image<Gray, byte>) : Cell list =
+    []
\ No newline at end of file
index 4891059..81bdbf8 100644 (file)
@@ -512,14 +512,14 @@ let private biquadroots (p: float[]) (r: float[,]) =
 
     quad ()
 
-
-let EEOverlapArea (e1: Types.Ellipse) (e2: Types.Ellipse) : float =
+// Return a tuple (area, x intersections, y intersections)
+let EEOverlapArea (e1: Types.Ellipse) (e2: Types.Ellipse) : (float * float[] * float[]) option =
     let h1, k1, a1, b1, phi_1 = e1.Cx, e1.Cy, e1.A, e1.B, e1.Alpha
     let h2, k2, a2, b2, phi_2 = e2.Cx, e2.Cy, e2.A, e2.B, e2.Alpha
 
     if a1 <= EPS || b1 <= EPS || a2 <= EPS || b2 <= EPS 
     then
-        -1.0
+        None
     else
         let phi_1 = phi_1 % Math.PI
         let phi_2 = phi_2 % Math.PI
@@ -696,22 +696,24 @@ let EEOverlapArea (e1: Types.Ellipse) (e2: Types.Ellipse) : float =
         
         if returnValue = -1.0
         then
-            returnValue
+            None
         else
-            match nintpts with
-            | 0 | 1 -> nointpts a1 b1 a2 b2 h1 k1 h2 k2 phi_1 phi_2 h2_tr k2_tr aa bb cc dd ee ff
-            | 2 -> match istanpt xint.[0] yint.[0] a1 b1 aa bb cc dd ee ff with
-                   | TANGENT_POINT -> 
+            let area =
+                match nintpts with
+                | 0 | 1 -> nointpts a1 b1 a2 b2 h1 k1 h2 k2 phi_1 phi_2 h2_tr k2_tr aa bb cc dd ee ff
+                | 2 -> match istanpt xint.[0] yint.[0] a1 b1 aa bb cc dd ee ff with
+                       | TANGENT_POINT -> 
 #if DEBUG_LOG
-                        printf "one point is tangent\n"
+                            printf "one point is tangent\n"
 #endif
-                        nointpts a1 b1 a2 b2 h1 k1 h2 k2 phi_1 phi_2 h2_tr k2_tr aa bb cc dd ee ff
+                            nointpts a1 b1 a2 b2 h1 k1 h2 k2 phi_1 phi_2 h2_tr k2_tr aa bb cc dd ee ff
 
-                   | INTERSECTION_POINT -> 
+                       | INTERSECTION_POINT -> 
 #if DEBUG_LOG
-                        printf "check twointpts\n"
+                            printf "check twointpts\n"
 #endif
-                        twointpts xint yint a1 b1 phi_1 a2 b2 h2_tr k2_tr phi_2 aa bb cc dd ee ff
-            | 3 -> threeintpts xint yint a1 b1 phi_1 a2 b2 h2_tr k2_tr phi_2 aa bb cc dd ee ff
-            | 4 -> fourintpts xint yint a1 b1 phi_1 a2 b2 h2_tr k2_tr phi_2 aa bb cc dd ee ff
-            | _ -> -1.0
+                            twointpts xint yint a1 b1 phi_1 a2 b2 h2_tr k2_tr phi_2 aa bb cc dd ee ff
+                | 3 -> threeintpts xint yint a1 b1 phi_1 a2 b2 h2_tr k2_tr phi_2 aa bb cc dd ee ff
+                | 4 -> fourintpts xint yint a1 b1 phi_1 a2 b2 h2_tr k2_tr phi_2 aa bb cc dd ee ff
+                | _ -> -1.0
+            Some (area, xint.[..nintpts-1], yint.[..nintpts-1])
\ No newline at end of file
index 0b96757..21616af 100644 (file)
@@ -11,13 +11,13 @@ open ImgTools
 open Config
 open Types
 
-type Result = {
+(*type Result = {
     RBCPositions : Point list
     infectedRBCPositions : Point list
     img: Image<Bgr, byte>
-}
+}*)
 
-let doAnalysis (img: Image<Bgr, byte>) (config: Config) : Result =
+let doAnalysis (img: Image<Bgr, byte>) (config: Config) : Classifier.Cell list =
 
     let imgFloat = img.Convert<Bgr, float32>()
     use scaledImg = if config.scale = 1.0 then imgFloat else imgFloat.Resize(config.scale, CvEnum.Inter.Area)
@@ -75,16 +75,8 @@ let doAnalysis (img: Image<Bgr, byte>) (config: Config) : Result =
 
     use magnitudesByte = ((magnitudes / !max) * 255.0).Convert<byte>() // Otsu from OpenCV only support 'byte'.
     use edges = new Matrix<byte>(xEdges.Size)    
-    let threshold = CvInvoke.Threshold(magnitudesByte, edges, 0.0, 1.0, CvEnum.ThresholdType.Otsu ||| CvEnum.ThresholdType.Binary)
-
-//    let filteredGreenMat = new Matrix<float32>(filteredGreen.Size)
-//    filteredGreen.CopyTo(filteredGreenMat)
-    let parasites = ParasitesMarker.find green filteredGreen config
-    
-    saveImg parasites.darkStain "parasites_dark_stain.png"
-    saveImg parasites.stain "parasites_stain.png"
-    saveImg parasites.infection "parasites_infection.png"
-    
+    CvInvoke.Threshold(magnitudesByte, edges, 0.0, 1.0, CvEnum.ThresholdType.Otsu ||| CvEnum.ThresholdType.Binary) |> ignore
+        
     logTime "Finding edges" (fun() ->
         thin edges)
 
@@ -93,6 +85,15 @@ let doAnalysis (img: Image<Bgr, byte>) (config: Config) : Result =
     
     saveMat (edges * 255.0) "edges.png" 
 
+
+    let kmediansResults = KMedians.kmedians filteredGreen 1.0
+
+    let parasites = ParasitesMarker.find green filteredGreen kmediansResults config
+    
+    saveImg parasites.darkStain "parasites_dark_stain.png"
+    saveImg parasites.stain "parasites_stain.png"
+    saveImg parasites.infection "parasites_infection.png"
+
     let radiusRange = config.scale * 20.0, config.scale * 40.0
     let windowSize = roundInt (1.6 * (snd radiusRange))
     let factorNbPick = 1.5
@@ -102,7 +103,7 @@ let doAnalysis (img: Image<Bgr, byte>) (config: Config) : Result =
     drawEllipses img ellipses (Bgr(0.0, 255.0, 255.0))
     //saveImg img "ellipses.png"
 
-    { RBCPositions = []; infectedRBCPositions = []; img = img }
+    Classifier.findCells ellipses parasites kmediansResults.fg
 
     // 
    
index afc4ab7..9b870dc 100644 (file)
@@ -50,12 +50,14 @@ type MatchingEllipses (radiusMin: float) =
                 if not other.Processed
                 then
                     let areaOther = other.Ellipse.Area
-                    let commonArea = EEOver.EEOverlapArea e.Ellipse other.Ellipse
-                    let matchingScore = 2.0 * commonArea / (areaE + areaOther)
-                    if matchingScore >= matchingScoreThreshold1
-                    then
-                        other.AddMatchingScore(matchingScore)
-                        e.AddMatchingScore(matchingScore)
+                    match EEOver.EEOverlapArea e.Ellipse other.Ellipse with
+                    | Some (commonArea, _, _) ->
+                        let matchingScore = 2.0 * commonArea / (areaE + areaOther)
+                        if matchingScore >= matchingScoreThreshold1
+                        then
+                            other.AddMatchingScore(matchingScore)
+                            e.AddMatchingScore(matchingScore)
+                    | _ -> ()
 
         // 3) Sort ellipses by their score.
         ellipses.Sort(fun e1 e2 -> e2.MatchingScore.CompareTo(e1.MatchingScore))
index 388b059..a14f11c 100644 (file)
     <Compile Include="Types.fs" />
     <Compile Include="ImgTools.fs" />
     <Compile Include="Config.fs" />
+    <Compile Include="KMedians.fs" />
     <Compile Include="EEOver.fs" />
+    <Compile Include="ParasitesMarker.fs" />
     <Compile Include="KdTree.fs" />
+    <Compile Include="Classifier.fs" />
     <Compile Include="MatchingEllipses.fs" />
     <Compile Include="Ellipse.fs" />
-    <Compile Include="KMedians.fs" />
-    <Compile Include="ParasitesMarker.fs" />
     <Compile Include="ImageAnalysis.fs" />
     <Compile Include="Program.fs" />
     <None Include="App.config" />
index 44da901..fde0afe 100644 (file)
@@ -10,10 +10,10 @@ type Result = {
     stain: Image<Gray, byte>
     infection: Image<Gray, byte> }
 
-let find (green: Image<Gray, float32>) (filteredGreen: Image<Gray, float32>) (config: Config.Config) : Result =
+let find (green: Image<Gray, float32>) (filteredGreen: Image<Gray, float32>) (kmediansResult: KMedians.Result) (config: Config.Config) : Result =
 
     // We use the filtered image to find the dark stain.
-    let { KMedians.fg = fg; KMedians.median_bg = median_bg; KMedians.median_fg = median_fg; KMedians.d_fg = d_fg } = KMedians.kmedians filteredGreen 1.0
+    let { KMedians.fg = fg; KMedians.median_bg = median_bg; KMedians.median_fg = median_fg; KMedians.d_fg = d_fg } = kmediansResult
     let darkStain = d_fg.Cmp(median_bg * config.darkStainLevel, CvEnum.CmpType.GreaterThan)
     darkStain._And(filteredGreen.Cmp(median_fg, CvEnum.CmpType.LessThan))
     darkStain._And(fg)
index fd9a2f9..46e870f 100644 (file)
@@ -66,6 +66,6 @@ do
 
     let result = ImageAnalysis.doAnalysis img config
     
-    display mainWindow result.img
+    display mainWindow img
     mainWindow.Root.Show()
     app.Run() |> ignore