From: Greg Burri Date: Fri, 22 May 2015 10:28:33 +0000 (+0200) Subject: Ajout de deux fonctions : X-Git-Url: https://git.euphorik.ch/?a=commitdiff_plain;h=4f3df3690c8712efcf879e4c01cd0f3536d7c6e5;p=malaria.git Ajout de deux fonctions : * L'algorithme wathershed à partir d'une transformé de distance. * Une fonction permettant l'écriture du gradient d'une image logique. --- diff --git a/current.psd b/current.psd index e18a1b5..9eca60a 100644 Binary files a/current.psd and b/current.psd differ diff --git a/rapport/main.tex b/rapport/main.tex index b408146..ec26011 100644 --- a/rapport/main.tex +++ b/rapport/main.tex @@ -102,8 +102,9 @@ Un filtre médian 5 x 5 suivi d'une fermeture par aire de 1000 sont appliqués \subsubsection{Granulometrie} -L'objectif ici est de déterminé la taille moyenne des +L'objectif ici est de déterminer le rayon moyenne des globules rouges (souvent abrégé \emph{RBC} pour \emph{red blood cell}). Pour ce faire nous allons réaliser une succession de fermetures à l'aide d'un élément structurant de forme octogonale dont le rayon va être augmenté à chaque itération sur la composante \emph{saturation} ($imgFiltered\{2\}$). Nous évitons ici un élément structurant ayant la forme d'un disque pour des raisons de performance, une fermeture avec ce dernier demandant beaucoup plus de calculs à effectuer. +Nous partons d'un rayon initial de 1 pour arriver à un rayon maximal de $largeur(imgRGB) / 35$. À chaque itération une fermeture est effectuée suivi du calcul du volume relatif de l'image : $volume(imgClosed) \rightarrow A, 1 - A / volImg \rightarrow N$ où $volImg$ est le volume de $imgFiltered\{2\}$. diff --git a/src/DetectionOfParasites.m b/src/DetectionOfParasites.m index b699d6b..36af6d2 100644 --- a/src/DetectionOfParasites.m +++ b/src/DetectionOfParasites.m @@ -11,7 +11,7 @@ function [THS, RBCRadius, nucleiRadius] = DetectionOfParasites(imgRGB) imgH = imgHSV(:, :, 1) * 255; % We shift the hue to have the greatest value for the nuclei. - hueShiftValue = 175; + hueShiftValue = 100; % 175; imgH = uint8(mod(255 - imgH + hueShiftValue, 256)); imwrite(imgH, '../output/imgH.png') diff --git a/src/Main.m b/src/Main.m index 48a1cae..c275618 100644 --- a/src/Main.m +++ b/src/Main.m @@ -26,9 +26,10 @@ delete('../output/*'); %% 13 mai 2015 -% imagePath = '13.05.2015/1412151257-100x-Teinte30-Saturation3-0013.tif'; -imagePath = '13.05.2015/1412151257-100x-Teinte30-Saturation3-0014.tif'; % Good result. +imagePath = '13.05.2015/1412151257-100x-Teinte30-Saturation3-0013.tif'; +% imagePath = '13.05.2015/1412151257-100x-Teinte30-Saturation3-0014.tif'; % Good result. % imagePath = '13.05.2015/1412151257-100x-Teinte0-Saturation0-0015.tif'; % Bad result. +% imagePath = '13.05.2015/1412151257-100x-0010.tif'; segmentationMethod = SegmentationMethod.WatershedByMorphologicalGradient; diff --git a/src/SegmentationOfRedCells.m b/src/SegmentationOfRedCells.m index dde8483..c9b1a6a 100644 --- a/src/SegmentationOfRedCells.m +++ b/src/SegmentationOfRedCells.m @@ -89,6 +89,9 @@ function [segmentedCells] = SegmentationOfRedCells(imgRGB, RBCRadius, WBC, schiz imwrite(compositesOpenedGradientThresholdHolesFilled, '../output/red cells segmentation - composites opened gradient threshold holes filled.png') compositesThinning = mmthin(compositesOpenedGradientThresholdHolesFilled); + + imwrite(compositesThinning, '../output/red cells segmentation - composites thinning 1.png') + compositesThinningFlooded = mmareaclose(compositesThinning, 5 * RBCRadiusMinArea); compositesThinningFlooded(compositesThinning) = 0; compositesThinningFlooded = mmero(compositesThinningFlooded); % We erode by a 3x3 cross to avoid the composites to touch the singles when fusionning later. diff --git a/src/WatershedsByDistanceTransform.m b/src/WatershedsByDistanceTransform.m new file mode 100644 index 0000000..e7fbe1c --- /dev/null +++ b/src/WatershedsByDistanceTransform.m @@ -0,0 +1,24 @@ +% Watershed from a distance transformation. +% Inspired by: http://mmorph.com/mxmorph/html/mmdemos/mmdcells.html. +% img: A binary image. +function [result] = WatershedsByDistanceTransform(img) + if ~islogical(img) + ME = MException('WatershedsByDistanceTransform:invalid_input_type', 'the input type must be logical'); + throw(ME) + end + + % Distance transform. Higher values denote the centers of cells. + distances = mmdist(img, mmsebox, 'EUCLIDEAN'); + + % Search the regional maximums to locate the center of each cell. + regionalMax = mmregmax(distances); + + % To merge some very near detected cells, avoid some isolated pixels. + dilatedRegionalMax = mmdil(regionalMax, mmsedisk(5, '2D', 'EUCLIDEAN')); + + % Apply the watershed algorithme to flood each cell from they center and find their boundaries. + cellBoundaries = mmcwatershed(mmneg(distances), dilatedRegionalMax, mmsebox); + + % Cut the cells. + result = mmintersec(img, mmneg(cellBoundaries)); +end \ No newline at end of file diff --git a/src/WriteImageGradient.m b/src/WriteImageGradient.m new file mode 100644 index 0000000..a1e0676 --- /dev/null +++ b/src/WriteImageGradient.m @@ -0,0 +1,20 @@ +% From a logical image 'img', a gradient is calculated +% then colored with color and written in 'filename'. +function WriteImageGradient(img, filename, color) + gradientImg = mmgradm(img); + [M, N] = size(gradientImg); + red = zeros(M, N, 'uint8'); + green = zeros(M, N, 'uint8'); + blue = zeros(M, N, 'uint8'); + alphaChannel = zeros(M, N, 'double'); + + red(gradientImg) = color(1); + green(gradientImg) = color(2); + blue(gradientImg) = color(3); + alphaChannel(gradientImg) = 1; + + rgb = cat(3, red, green, blue); + + imwrite(rgb, filename, 'Alpha', alphaChannel) +end +