From: Greg Burri Date: Fri, 11 Dec 2015 16:27:43 +0000 (+0100) Subject: beginning of the classifier. X-Git-Tag: 1.0.11~84 X-Git-Url: http://git.euphorik.ch/?p=master-thesis.git;a=commitdiff_plain;h=06bd63d8c01100c28873dfafd59b5efccbfb67e4 beginning of the classifier. --- diff --git a/Parasitemia/Parasitemia/Classifier.fs b/Parasitemia/Parasitemia/Classifier.fs new file mode 100644 index 0000000..6441635 --- /dev/null +++ b/Parasitemia/Parasitemia/Classifier.fs @@ -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 } + +let findCells (ellipses: Types.Ellipse list) (parasites: ParasitesMarker.Result) (fg: Image) : Cell list = + [] \ No newline at end of file diff --git a/Parasitemia/Parasitemia/EEOver.fs b/Parasitemia/Parasitemia/EEOver.fs index 4891059..81bdbf8 100644 --- a/Parasitemia/Parasitemia/EEOver.fs +++ b/Parasitemia/Parasitemia/EEOver.fs @@ -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 diff --git a/Parasitemia/Parasitemia/ImageAnalysis.fs b/Parasitemia/Parasitemia/ImageAnalysis.fs index 0b96757..21616af 100644 --- a/Parasitemia/Parasitemia/ImageAnalysis.fs +++ b/Parasitemia/Parasitemia/ImageAnalysis.fs @@ -11,13 +11,13 @@ open ImgTools open Config open Types -type Result = { +(*type Result = { RBCPositions : Point list infectedRBCPositions : Point list img: Image -} +}*) -let doAnalysis (img: Image) (config: Config) : Result = +let doAnalysis (img: Image) (config: Config) : Classifier.Cell list = let imgFloat = img.Convert() 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) (config: Config) : Result = use magnitudesByte = ((magnitudes / !max) * 255.0).Convert() // Otsu from OpenCV only support 'byte'. use edges = new Matrix(xEdges.Size) - let threshold = CvInvoke.Threshold(magnitudesByte, edges, 0.0, 1.0, CvEnum.ThresholdType.Otsu ||| CvEnum.ThresholdType.Binary) - -// let filteredGreenMat = new Matrix(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) (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) (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 // diff --git a/Parasitemia/Parasitemia/MatchingEllipses.fs b/Parasitemia/Parasitemia/MatchingEllipses.fs index afc4ab7..9b870dc 100644 --- a/Parasitemia/Parasitemia/MatchingEllipses.fs +++ b/Parasitemia/Parasitemia/MatchingEllipses.fs @@ -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)) diff --git a/Parasitemia/Parasitemia/Parasitemia.fsproj b/Parasitemia/Parasitemia/Parasitemia.fsproj index 388b059..a14f11c 100644 --- a/Parasitemia/Parasitemia/Parasitemia.fsproj +++ b/Parasitemia/Parasitemia/Parasitemia.fsproj @@ -66,12 +66,13 @@ + + + - - diff --git a/Parasitemia/Parasitemia/ParasitesMarker.fs b/Parasitemia/Parasitemia/ParasitesMarker.fs index 44da901..fde0afe 100644 --- a/Parasitemia/Parasitemia/ParasitesMarker.fs +++ b/Parasitemia/Parasitemia/ParasitesMarker.fs @@ -10,10 +10,10 @@ type Result = { stain: Image infection: Image } -let find (green: Image) (filteredGreen: Image) (config: Config.Config) : Result = +let find (green: Image) (filteredGreen: Image) (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) diff --git a/Parasitemia/Parasitemia/Program.fs b/Parasitemia/Parasitemia/Program.fs index fd9a2f9..46e870f 100644 --- a/Parasitemia/Parasitemia/Program.fs +++ b/Parasitemia/Parasitemia/Program.fs @@ -66,6 +66,6 @@ do let result = ImageAnalysis.doAnalysis img config - display mainWindow result.img + display mainWindow img mainWindow.Root.Show() app.Run() |> ignore