X-Git-Url: http://git.euphorik.ch/?p=master-thesis.git;a=blobdiff_plain;f=Parasitemia%2FParasitemiaCore%2FParasitesMarker.fs;h=b89caa68c02760b2dc4af0af0be28b48d4d12a1a;hp=22ea041be57de154cc494a7385e650013bdb2121;hb=2d712781def419c9acc98368f7102b19b064f16d;hpb=4bfa3cbdc6145e6944f02e24829ab2ef3a851ac1 diff --git a/Parasitemia/ParasitemiaCore/ParasitesMarker.fs b/Parasitemia/ParasitemiaCore/ParasitesMarker.fs index 22ea041..b89caa6 100644 --- a/Parasitemia/ParasitemiaCore/ParasitesMarker.fs +++ b/Parasitemia/ParasitemiaCore/ParasitesMarker.fs @@ -6,84 +6,61 @@ open System.Linq open Emgu.CV open Emgu.CV.Structure -open Logger - open Utils +open Histogram +open Otsu +open Morpho +open ImgTools -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 findMa (green: Image) (filteredGreen: Image) (config: Config.Config) : Result * Image * Image = - // We use the filtered image to find the dark stain. - let kmediansResults = Log.LogWithTime("Finding fg/bg (k-medians)", Severity.USER, (fun () -> KMedians.kmedians filteredGreen)) - 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 * float config.Parameters.darkStainLevel, CvEnum.CmpType.GreaterThan) - darkStain._And(filteredGreen.Cmp(median_fg, CvEnum.CmpType.LessThan)) - darkStain._And(fg) - - let fgFloat = (fg / 255.0).Convert() - use greenWithoutBg = ImgTools.gaussianFilter green 1.0 - greenWithoutBg.SetValue(Gray(0.0), fg.Not()) - - let findSmears (sigma: float) (level: float) : Image = - use greenWithoutBgSmoothed = ImgTools.gaussianFilter greenWithoutBg sigma - use fgSmoothed = ImgTools.gaussianFilter fgFloat sigma - let smears = (greenWithoutBg.Mul(fgSmoothed)).Cmp(greenWithoutBgSmoothed.Mul(level), CvEnum.CmpType.LessThan) - smears._And(fg) - smears - - let tmp = filteredGreen.Convert() +type Result = + { + darkStain : Image // Colored pixel, it's independent of the size of the areas. It corresponds to white cells, schizontes, gametocytes, throphozoites. + nucleus : Image // Parasite nucleus. It may contain some debris. It shouldn't contain thrombocytes or larger elements. + parasite : Image // The whole parasites. + } - { darkStain = darkStain; - stain = findSmears 10. 0.9 - infection = findSmears 2.2 0.87 }, - tmp, - tmp +let find (img : Image) (config : Config.Config) : Result * Image * 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) (config: Config.Config) : Result * Image = - use filteredGreenWithoutInfection = filteredGreen.Copy() - ImgTools.areaCloseF filteredGreenWithoutInfection (int config.RBCRadius.InfectionArea) - - let filteredGreenWithoutStain = filteredGreenWithoutInfection.Copy() - ImgTools.areaCloseF filteredGreenWithoutStain (int config.RBCRadius.StainArea) + let imgWithoutNucleus = img.Copy () + areaCloseF imgWithoutNucleus (roundInt config.RBCRadius.NucleusArea) let darkStain = // We use the filtered image to find the dark stain. let _, mean_fg, mean_bg = - let hist = ImgTools.histogramImg filteredGreenWithoutInfection 300 - ImgTools.otsu hist - filteredGreenWithoutInfection.Cmp(-(float mean_bg) * config.Parameters.darkStainLevel + (float mean_fg), CvEnum.CmpType.LessThan) - - let marker (img: Image) (closed: Image) (level: float) : Image = - let diff = img.Copy() - diff._Mul(level) - CvInvoke.Subtract(closed, diff, diff) - diff._ThresholdBinary(Gray(0.0), Gray(255.)) - diff.Convert() - - let infectionMarker = marker filteredGreen filteredGreenWithoutInfection (1. / config.Parameters.infectionSensitivity) - let stainMarker = marker filteredGreenWithoutInfection filteredGreenWithoutStain (1. / config.Parameters.stainSensitivity) - - // TODO: comprendre pourquoi des valeurs sont negatives!?!? - (* - let blackTopHat = filteredGreen.CopyBlank() - CvInvoke.Subtract(filteredGreenWithoutInfection, filteredGreen, blackTopHat) - ImgTools.saveImg (ImgTools.normalizeAndConvert blackTopHat) "BottomHat.png" - *) - - { darkStain = darkStain - infection = infectionMarker - stain = stainMarker }, - filteredGreenWithoutStain + let hist = histogramImg imgWithoutNucleus 300 + otsu hist + imgWithoutNucleus.Cmp (float mean_fg - config.Parameters.darkStainLevel * float (mean_bg - mean_fg), CvEnum.CmpType.LessThan) + + let marker (img : Image) (closed : Image) (level : float) : Image = + let diff = img.Copy () + diff._Mul level + CvInvoke.Subtract (closed, diff, diff) + diff._ThresholdBinary (Gray 0.0, Gray 255.) + diff.Convert () + + // Nucleus. + let nucleusMarker = marker img imgWithoutNucleus (1. / config.Parameters.infectionSensitivity) + + // Cytoplasm. + let imgWithoutParasite = img.CopyBlank () + let kernelSize = + let size = roundInt config.RBCRadius.CytoplasmSize + if size % 2 = 0 then size + 1 else size + use kernel = + if kernelSize <= 3 then + CvInvoke.GetStructuringElement (CvEnum.ElementShape.Rectangle, Size (3, 3), Point (-1, -1)) + else + CvInvoke.GetStructuringElement (CvEnum.ElementShape.Ellipse, Size (kernelSize, kernelSize), Point (-1, -1)) + + CvInvoke.MorphologyEx (img, imgWithoutParasite, CvEnum.MorphOp.Close, kernel, Point(-1, -1), 1, CvEnum.BorderType.Replicate, MCvScalar()) + let parasiteMarker = marker img imgWithoutParasite (1. / config.Parameters.cytoplasmSensitivity) + + { + darkStain = darkStain + nucleus = nucleusMarker + parasite = parasiteMarker + }, + imgWithoutParasite, + imgWithoutNucleus