From: Greg Burri Date: Fri, 1 Jan 2016 09:39:27 +0000 (+0100) Subject: Simplification of the parasite marker. X-Git-Tag: 1.0.11~70 X-Git-Url: http://git.euphorik.ch/?p=master-thesis.git;a=commitdiff_plain;h=f9ee9f2c0c1194a6a8f7475ee2ca0b7076b32261 Simplification of the parasite marker. --- diff --git a/Parasitemia/Parasitemia/Classifier.fs b/Parasitemia/Parasitemia/Classifier.fs index 3113d6f..99b6edc 100644 --- a/Parasitemia/Parasitemia/Classifier.fs +++ b/Parasitemia/Parasitemia/Classifier.fs @@ -21,7 +21,7 @@ type private EllipseFlaggedKd (e: Ellipse) = member this.Y = this.Cy -let findCells (ellipses: Ellipse list) (parasites: ParasitesMarker2.Result) (img: Image) (config: Config.Config) : Cell list = +let findCells (ellipses: Ellipse list) (parasites: ParasitesMarker.Result) (img: Image) (config: Config.Config) : Cell list = if ellipses.IsEmpty then [] @@ -162,7 +162,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.parasitePixelsRequired + elif infectedPixels.Count >= 1 then let infectionToRemove = ImgTools.connectedComponents parasites.stain infectedPixels for p in infectionToRemove do diff --git a/Parasitemia/Parasitemia/Config.fs b/Parasitemia/Parasitemia/Config.fs index 5cf392c..45b1ca3 100644 --- a/Parasitemia/Parasitemia/Config.fs +++ b/Parasitemia/Parasitemia/Config.fs @@ -23,12 +23,11 @@ type Parameters = { maxDarkStainRatio: float stainArea: float // Factor of a RBC area. 0.5 means the half of RBC area. - stainLevel: float // [0, 2] + stainLevel: float // > 1 maxStainRatio: float // [0, 1] infectionArea: float // Factor of a RBC area. 0.5 means the half of RBC area. - infectionLevel: float // [0, 2] - parasitePixelsRequired: int + infectionLevel: float // > 1 standardDeviationMaxRatio: float // The standard deviation of the pixel values of a cell can't be greater than standardDeviationMaxRatio * global standard deviation minimumCellArea: float // Factor of RBC area. diff --git a/Parasitemia/Parasitemia/MainAnalysis.fs b/Parasitemia/Parasitemia/MainAnalysis.fs index fd341ac..c987e63 100644 --- a/Parasitemia/Parasitemia/MainAnalysis.fs +++ b/Parasitemia/Parasitemia/MainAnalysis.fs @@ -42,7 +42,8 @@ let doAnalysis (img: Image) (name: string) (config: Config) : Cell li let filteredGreenFloat = filteredGreen.Convert() // Is it neccessary? - let parasites, filteredGreenWhitoutInfection, filteredGreenWhitoutStain = ParasitesMarker2.find filteredGreen filteredGreenFloat config + let parasites, filteredGreenWhitoutInfection, filteredGreenWhitoutStain = ParasitesMarker.find filteredGreen filteredGreenFloat config + //let parasites, filteredGreenWhitoutInfection, filteredGreenWhitoutStain = ParasitesMarker.findMa greenFloat filteredGreenFloat config let filteredGreenWhitoutInfectionFloat = filteredGreenWhitoutInfection.Convert() let filteredGreenWhitoutStainFloat = filteredGreenWhitoutStain.Convert() diff --git a/Parasitemia/Parasitemia/Parasitemia.fsproj b/Parasitemia/Parasitemia/Parasitemia.fsproj index fe81290..3282961 100644 --- a/Parasitemia/Parasitemia/Parasitemia.fsproj +++ b/Parasitemia/Parasitemia/Parasitemia.fsproj @@ -72,7 +72,6 @@ - diff --git a/Parasitemia/Parasitemia/ParasitesMarker.fs b/Parasitemia/Parasitemia/ParasitesMarker.fs index d1a51fa..20dbf4c 100644 --- a/Parasitemia/Parasitemia/ParasitesMarker.fs +++ b/Parasitemia/Parasitemia/ParasitesMarker.fs @@ -1,23 +1,27 @@ module ParasitesMarker open System.Drawing +open System.Linq open Emgu.CV open Emgu.CV.Structure +open Utils type Result = { darkStain: Image - stain: Image - infection: Image } + infection: Image + stain: Image } + // Create three binary markers : // * 'Dark stain' corresponds to the colored pixel, it's independent of the size of the areas. // * 'Stain' corresponds to the stain around the parasites. // * 'Infection' corresponds to the parasite. It shouldn't contain thrombocytes. -(*let find (green: Image) (filteredGreen: Image) (kmediansResult: KMedians.Result) (config: Config.Config) : Result = +let findMa (green: Image) (filteredGreen: Image) (config: Config.Config) : Result * Image * Image = // 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 } = kmediansResult + let kmediansResults = logTime "Finding fg/bg (k-medians)" (fun () -> KMedians.kmedians filteredGreen 1.0) + let { KMedians.fg = fg; KMedians.median_bg = median_bg; KMedians.median_fg = median_fg; KMedians.d_fg = d_fg } = kmediansResults let darkStain = d_fg.Cmp(median_bg * config.Parameters.darkStainLevel, CvEnum.CmpType.GreaterThan) darkStain._And(filteredGreen.Cmp(median_fg, CvEnum.CmpType.LessThan)) darkStain._And(fg) @@ -33,9 +37,50 @@ type Result = { smears._And(fg) smears + let tmp = filteredGreen.Convert() + { darkStain = darkStain; - stain = findSmears config.Parameters.stainSigma config.Parameters.stainLevel - infection = findSmears config.Parameters.infectionSigma config.Parameters.infectionLevel }*) + stain = findSmears 10. 0.9 + infection = findSmears 2.2 0.87 }, + tmp, + tmp + + +// Create three binary markers : +// * 'Dark stain' corresponds to the colored pixel, it's independent of the size of the areas. +// * 'Stain' corresponds to the stain around the parasites. +// * 'Infection' corresponds to the parasite. It shouldn't contain thrombocytes. +let find (filteredGreen: Image) (filteredGreenFloat: Image) (config: Config.Config) : Result * Image * Image = + + let filteredGreenWithoutInfection = filteredGreen.Copy() + ImgTools.areaClose filteredGreenWithoutInfection (int config.InfectionArea) + + let filteredGreenWithoutStain = filteredGreenWithoutInfection.Copy() + ImgTools.areaClose filteredGreenWithoutStain (int config.StainArea) + + // We use the filtered image to find the dark stain. + let kmediansResults = logTime "Finding fg/bg (k-medians)" (fun () -> KMedians.kmedians (filteredGreenWithoutInfection.Convert()) 1.0) // FIXME: avoid converting again this in MainAnalysis + let { KMedians.fg = fg; KMedians.median_bg = median_bg; KMedians.median_fg = median_fg; KMedians.d_fg = d_fg } = kmediansResults + let darkStain = d_fg.Cmp(median_bg * config.Parameters.darkStainLevel, CvEnum.CmpType.GreaterThan) + darkStain._And(filteredGreenWithoutInfection.Cmp(median_fg, CvEnum.CmpType.LessThan)) + + let marker (img: Image) (closed: Image) (level: float) : Image = + let diff = closed - (img * level) + diff._ThresholdBinary(Gray(0.0), Gray(255.)) + diff + + let infectionMarker = marker filteredGreen filteredGreenWithoutInfection config.Parameters.infectionLevel + let stainMarker = marker filteredGreenWithoutInfection filteredGreenWithoutStain config.Parameters.stainLevel + + { darkStain = darkStain + infection = infectionMarker + stain = stainMarker }, + filteredGreenWithoutInfection, + filteredGreenWithoutStain + + + + diff --git a/Parasitemia/Parasitemia/ParasitesMarker2.fs b/Parasitemia/Parasitemia/ParasitesMarker2.fs deleted file mode 100644 index 42645b4..0000000 --- a/Parasitemia/Parasitemia/ParasitesMarker2.fs +++ /dev/null @@ -1,69 +0,0 @@ -module ParasitesMarker2 - -open System.Drawing -open System.Linq - -open Emgu.CV -open Emgu.CV.Structure - -open Utils - -type Result = { - darkStain: Image - infection: Image - stain: Image } - -// Create three binary markers : -// * 'Dark stain' corresponds to the colored pixel, it's independent of the size of the areas. -// * 'Stain' corresponds to the stain around the parasites. -// * 'Infection' corresponds to the parasite. It shouldn't contain thrombocytes. -let find (filteredGreen: Image) (filteredGreenFloat: Image) (config: Config.Config) : Result * Image * Image = - - let filteredGreenWithoutInfection = filteredGreen.Copy() - ImgTools.areaClose filteredGreenWithoutInfection (int config.InfectionArea) - - let filteredGreenWithoutStain = filteredGreenWithoutInfection.Copy() - ImgTools.areaClose filteredGreenWithoutStain (int config.StainArea) - - // We use the filtered image to find the dark stain. - let kmediansResults = logTime "Finding fg/bg (k-medians)" (fun () -> KMedians.kmedians (filteredGreenWithoutInfection.Convert()) 1.0) // FIXME: avoid converting again this in MainAnalysis - let { KMedians.fg = fg; KMedians.median_bg = median_bg; KMedians.median_fg = median_fg; KMedians.d_fg = d_fg } = kmediansResults - let darkStain = d_fg.Cmp(median_bg * config.Parameters.darkStainLevel, CvEnum.CmpType.GreaterThan) - darkStain._And(filteredGreenWithoutInfection.Cmp(median_fg, CvEnum.CmpType.LessThan)) - - let marker (img: Image) (closed: Image) (level: float) : Image = - let diff = closed - img - - let min = ref [| 0. |] - let minLocation = ref <| [| Point() |] - let max = ref [| 0. |] - let maxLocation = ref <| [| Point() |] - diff.MinMax(min, max, minLocation, maxLocation) - let max = (!max).[0] - - let threshold = 0.2 * max - let diff' = diff - threshold - - let m = MathNet.Numerics.Statistics.StreamingStatistics.Mean(seq { - for m in ImgTools.findMaxima diff' do - let p = m.First() - yield diff'.Data.[p.Y, p.X, 0] |> float }) + threshold - - let valueThreshold = m * level - - diff._ThresholdBinary(Gray(valueThreshold), Gray(255.)) - diff - - let infectionMarker = marker filteredGreen filteredGreenWithoutInfection config.Parameters.infectionLevel - let stainMarker = marker filteredGreenWithoutInfection filteredGreenWithoutStain config.Parameters.stainLevel - - { darkStain = darkStain - infection = infectionMarker - stain = stainMarker }, - filteredGreenWithoutInfection, - filteredGreenWithoutStain - - - - - diff --git a/Parasitemia/Parasitemia/Program.fs b/Parasitemia/Parasitemia/Program.fs index 25c707d..528f2de 100644 --- a/Parasitemia/Parasitemia/Program.fs +++ b/Parasitemia/Parasitemia/Program.fs @@ -73,11 +73,10 @@ let main args = maxDarkStainRatio = 0.1 infectionArea = 0.012 // 1.2 % - infectionLevel = 0.85 - parasitePixelsRequired = 1 + infectionLevel = 1.12 // Lower -> more sensitive. - stainArea = 0.08 - stainLevel = 0.85 + stainArea = 0.08 // 8 % + stainLevel = 1.1 // Lower -> more sensitive. maxStainRatio = 0.12 // 12 % standardDeviationMaxRatio = 0.55