-
Notifications
You must be signed in to change notification settings - Fork 0
/
nuclei_counter.m
91 lines (73 loc) · 3.21 KB
/
nuclei_counter.m
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
function [outputImage, number_of_nuclei, afterLoG, binarization] = nuclei_counter(sourceImage, threshold)
% This script accept an input nuclei image taken under microscope,
% then preprocess the image with tophat and bottomhat filter, enhance its
% contrast by multiplying gamma. Convert it to binary image with a histogram
% based threshold, count the number of connected components and detect edges
% of nucleus with LoG filter, then plot edges. Or calculate distance transform
% and detect seed points,use watershed algorithm for segmentation.
%
% flow chart:
% input image ---> tophat/bottomhat filter ---> image enhancement--->binarization by a histogram based threshold
% ---> calculate seed points ---> segmentation or plot edges of blobs ---> count connected components
%
% refrence:
% * Yousef Al-Kofahi, et al. Improved Automatic Detection and Segmentation of Cell Nuclei in Histopathology Images.
% IEEE TRANSACTIONS ON BIOMEDICAL ENGINEERING, VOL. 57, NO. 4, APRIL 2010
% * Jos B.T.M, et al, The Watershed Transform: Defnitions, Algorithms and Parallelization Strategies
% Fundamenta Informaticae 41 (2001) 187{228
%
% Input
% sourceImage: 8 bits grayscale image;
% threshold: threshold [0 1] for binarization.
%
% Output:
% outputImage: source image with overlayed contour
% number_of_nuclei: number of nucleis in image
%
% If you have any ideas or improvements about this method, welcome to contact me '[email protected]'.
% display original image
image = sourceImage;
figure;imshow(image,[min(image(:)) max(image(:))]);
title('input image');
total = numel(image);
% apply top hat and bottom hat filter
se = strel('disk',30);
tophat = imtophat(image,se);
bottomhat = imbothat(image,se);
filterImage = image + (tophat - bottomhat);
se = strel('disk',15);
tophat = imtophat(filterImage,se);
bottomhat = imbothat(filterImage,se);
filterImage = filterImage + (tophat - bottomhat);
% calculate histogram of filtered image
% estimate more than 78.5% area is background (pi/4 = .785)
[counts,x] = imhist(filterImage);
ssum = cumsum(counts);
bg = .215*total;
fg = .99*total;
low = find(ssum>bg, 1, 'first');
high = find(ssum>fg, 1, 'first');
adjustedImage = imadjust(filterImage, [low/255 high/255],[0 1],1.8);
% image binarization, threshold is choosen based on experience
if(nargin < 2)
matrix = reshape(adjustedImage,total,1);
matrix = sort(matrix);
threshold = graythresh(matrix(total*.5:end))/3; % adjust default threshold
end
binarization = im2bw(adjustedImage,threshold);
% open image and then detect edge using laplacian of gaussian
se2 = strel('disk',5);
afterOpening = imopen(binarization,se2);
nsize = 5; sigma = 3;
h = fspecial('log',nsize,sigma);
afterLoG = uint8(imfilter(double(afterOpening)*255,h,'same').*(sigma^2));
se2 = strel('disk',5);
afterOpening = imopen(binarization,se2);
number_of_nuclei = bwconncomp(afterOpening);
% % you can either use watershed method to do segmentation
% D = -bwdist(~afterOpening);
% D(~afterOpening) = -Inf;
% L = watershed(D);
outputImage = sourceImage + afterLoG*5;
figure;imshow(outputImage, [min(sourceImage(:)) max(sourceImage(:))]);
title('output image');