2
$\begingroup$

I am trying to segment the nucleus of the cell in an image so I can extract its boundary. The nucleus and the background of the image are very similar so I am finding it difficult to do this using the something like erosion.

If anyone could suggest a way to remove the background and keep the nucleus that would be very helpful.

Image:

cell nucleus

$\endgroup$

migrated from stackoverflow.com May 9 '14 at 15:02

This question came from our site for professional and enthusiast programmers.

  • $\begingroup$ Yes it is it's about segmentation methods $\endgroup$ – user3461851 May 8 '14 at 15:02
  • $\begingroup$ It's just the red central region I am trying to extract, but when converted to black and white, it doesn't work so well as the background is the same colour as it. $\endgroup$ – user3461851 May 8 '14 at 15:04
  • $\begingroup$ Have you looked at working on just the red channel? $\endgroup$ – Dan May 8 '14 at 15:08
  • $\begingroup$ @Dan I'm new to this, how exactly would I go about that. $\endgroup$ – user3461851 May 8 '14 at 15:13
  • 1
    $\begingroup$ RGB's approach is fast and can provide a quick fix, but there might be red in other parts of the image. Converting to HSV is an option, or YCbCr as suggested by @Shai $\endgroup$ – Cape Code May 8 '14 at 15:27
6
$\begingroup$

You need to work with different color space. Try YCbCr for instance

oimg = imread('http://i.stack.imgur.com/aYhrS.png');
img = rgb2ycbcr(oimg); % conver RGB to YCbCr color space
msk = img(:,:,3)>130;  % apply threshold on Cr channel to get segmentation mask

I picked up 130 as arbitrary threshold, you might need to adjust it a bit.
Showing the input image, the image region for which msk==1, and the background: enter image description here

I'll leave it to you as an exercise to think why the Cr channel performed well for this image.

$\endgroup$
2
$\begingroup$

The reason you're running into difficulty is because you're doing a black-white conversion, and this step is "throwing out" your best differentiating feature. Try doing the segmentation in a non b-w color space. The segmentation itself can be done pretty easily using k-means clustering:

img = imread('http://i.stack.imgur.com/aYhrS.png');
imshow(img)

cform = makecform('srgb2lab');
lab_he = applycform(img,cform);

% classify the colors in 'a*b*' Space Using k-means clustering
ab = double(lab_he(:,:,2:3));
nrows = size(ab,1);
ncols = size(ab,2);
ab = reshape(ab,nrows*ncols,2);

% Looks like there are ~3 colors in the image
nColors = 3;

% repeat the clustering 3 times to avoid local minima
[cluster_idx, cluster_center] = kmeans(ab,nColors,'distance','sqEuclidean', ...
                                  'Replicates',3);

pixel_labels = reshape(cluster_idx,nrows,ncols);

% nucleus is in the center. figure out what its label is.
middleX = round(size(img,2)/2);
middleY = round(size(img,1)/2);

nucleusLabel = pixel_labels(middleX,middleY);

figure
tempImg = bsxfun(@eq,pixel_labels,nucleusLabel);
tempImg = bsxfun(@times,double(tempImg),double(img));

imshowpair(img,tempImg/max(tempImg2(:)),'montage')

$\endgroup$
  • 1
    $\begingroup$ you can reshape without explicitly computing the number of points: ab=reshape( ab, [], 2 ); $\endgroup$ – Shai May 8 '14 at 15:34
  • 1
    $\begingroup$ you should use bsxfun to get tempImg from the mask pixel_labels ~= nucleusLabel instead of loop over the channels. $\endgroup$ – Shai May 8 '14 at 15:37
  • $\begingroup$ have you tried mean-shift segmentation? should preserve the spatial relations between the pixels... $\endgroup$ – Shai May 8 '14 at 15:38
  • 1
    $\begingroup$ Good point! Replaced the loop with bsxfun. Haven't tried mean-shift segmentation yet, though. $\endgroup$ – ChuckN May 8 '14 at 15:51

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy