# Matlab - Segment cell nucleus from similar background

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:

## migrated from stackoverflow.comMay 9 '14 at 15:02

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

• Yes it is it's about segmentation methods – user3461851 May 8 '14 at 15:02
• 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. – user3461851 May 8 '14 at 15:04
• Have you looked at working on just the red channel? – Dan May 8 '14 at 15:08
• @Dan I'm new to this, how exactly would I go about that. – user3461851 May 8 '14 at 15:13
• 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 – Cape Code May 8 '14 at 15:27

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:

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

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')


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