# Cell segmentation 119

Posted by **Steve Eddins**,

Blog reader Ramiro Massol asked for advice on segmenting his cell images, so I gave it a try. I'm not a microscopy expert, though, and I invite readers who have better suggestions than mine to add your comments below.

Let's take a look first to see what we have. I'm going to work with a cropped version of the original so that the images aren't too big for the layout of this blog.

*Note: you can download the functions imcredit and imoverlay from MATLAB Central.*

I = imread('https://blogs.mathworks.com/images/steve/60/nuclei.png'); I_cropped = I(400:900, 465:965); imshow(I_cropped) imcredit('Image courtesy of Dr. Ramiro Massol')

Strictly speaking, contrast adjustment isn't usually necessary for segmentation, but it can help the algorithm developer see
and understand the image data better. This is a fairly low-contrast image, so I thought it might help. You can adjust the
display contrast interactively with imtool, or you can use an automatic method such as adapthisteq. `adapthisteq` implements a technique called *contrast-limited adaptive histogram equalization*, or CLAHE. (I always thought "CLAHE" sounded like it must be some Klingon delicacy.)

I_eq = adapthisteq(I_cropped); imshow(I_eq)

So what happens if we just apply a threshold now?

bw = im2bw(I_eq, graythresh(I_eq)); imshow(bw)

Let's clean that up and then overlay the perimeter on the original image.

```
bw2 = imfill(bw,'holes');
bw3 = imopen(bw2, ones(5,5));
bw4 = bwareaopen(bw3, 40);
bw4_perim = bwperim(bw4);
overlay1 = imoverlay(I_eq, bw4_perim, [.3 1 .3]);
imshow(overlay1)
```

Now, I'm not familiar with these cell images, so I don't know exactly what I'm looking at. I assume some of these blobs need
more help to be separated properly. One possible approach is called *marker-based watershed segmentation*. There's a *demo* of this idea on The MathWorks web site.

With this method, you have to find a way to "mark" at least a partial group of connected pixels inside each object to be segmented. You also have to mark the background.

Let's try to use the bright objects, which I assume are nuclei. The *extended maxima* operator can be used to identify groups of pixels that are significantly higher than their immediate surrounding.

mask_em = imextendedmax(I_eq, 30); imshow(mask_em)

Let's clean that up and then overlay it.

```
mask_em = imclose(mask_em, ones(5,5));
mask_em = imfill(mask_em, 'holes');
mask_em = bwareaopen(mask_em, 40);
overlay2 = imoverlay(I_eq, bw4_perim | mask_em, [.3 1 .3]);
imshow(overlay2)
```

Next step: complement the image so that the peaks become valleys. We do this because we are about to apply the watershed transform, which identifies low points, not high points.

I_eq_c = imcomplement(I_eq);

Next: modify the image so that the background pixels and the extended maxima pixels are forced to be the only local minima in the image.

I_mod = imimposemin(I_eq_c, ~bw4 | mask_em);

Now compute the watershed transform.

L = watershed(I_mod); imshow(label2rgb(L))

I don't know if this is a good segmentation result or not, but I hope some of the methods I've shown will give Dr. Massol some ideas to try.

Other readers ... if you have suggestions, I invite you to post your comments here.

Get the MATLAB code

Published with MATLAB® 7.2

### Note

Comments are closed.

## 119 CommentsOldest to Newest

**1**of 119

**2**of 119

**3**of 119

**4**of 119

**5**of 119

**6**of 119

**7**of 119

**8**of 119

**9**of 119

**10**of 119

`adapthisteq`function.

**11**of 119

**12**of 119

**13**of 119

**14**of 119

**15**of 119

**16**of 119

mse = mean( (A(:) - B(:)).^2 );

**17**of 119

**18**of 119

**19**of 119

**20**of 119

**21**of 119

**22**of 119

**23**of 119

**24**of 119

**25**of 119

**26**of 119

`imclearborder`to remove objects touching the border.

**27**of 119

**28**of 119

**29**of 119

**30**of 119

**31**of 119

**32**of 119

**33**of 119

**34**of 119

`ones(5,5)/25`.

**35**of 119

**36**of 119

**37**of 119

[x,y] = meshgrid(linspace(-1,1,200)); bw = hypot(x,y) <= 0.25;

**38**of 119

**39**of 119

`bwlabel`and

`regionprops`.

**40**of 119

**41**of 119

**42**of 119

**43**of 119

**44**of 119

`bwlabel`to count them.

**45**of 119

**46**of 119

**47**of 119

**48**of 119

`imextendedmin`in order to filter out shallow minima.

**49**of 119

**50**of 119

**51**of 119

`bwlabel`and modify it to suit your needs. Look in the file for the line:

numComponents = length(sizes);That's the answer you are looking for, and that line occurs before the memory-consuming output label matrix is constructed.

**52**of 119

`bwlabel`and

`regionprops`to measure the area. I can't help you much with the segmentation problem. Image segmentation usually requires some custom algorithm development that depends on the specific characteristics of your data set. Consult texts on microscopy and image processing for some general methods that you might be able to adapt to your data.

**53**of 119

**54**of 119

**55**of 119

`imread`) to show how to read the correct original image directly, using its URL. I hope this will help others avoid similar confusion.

**56**of 119

**57**of 119

**58**of 119

**59**of 119

**60**of 119

**61**of 119

**62**of 119

**63**of 119

**64**of 119

**65**of 119

**66**of 119

[L, num_cells] = bwlabel(segmented_cell_image);

**67**of 119

**68**of 119

**69**of 119

**70**of 119

**71**of 119

**72**of 119

**73**of 119

**74**of 119

**75**of 119

**76**of 119

**77**of 119

**78**of 119

**79**of 119

**80**of 119

**81**of 119

`imoverlay`.

**82**of 119

**83**of 119

**84**of 119

**85**of 119

**86**of 119

**87**of 119

**88**of 119

**89**of 119

**90**of 119

**91**of 119

`bwlabel`to

`regionprops`to get the centroid of each labeled object.

**92**of 119

**93**of 119

**94**of 119

`watershed`to the function

`regionprops`in order to calculate the desired measurements for each labeled region.

**95**of 119

dist = hypot(centroid1 - centroid2);

**96**of 119

**97**of 119

**98**of 119

**99**of 119

**100**of 119

**101**of 119

**102**of 119

`bwlabel`and

`regionprops`.

**103**of 119

**104**of 119

**105**of 119

**106**of 119

**107**of 119

**108**of 119

**109**of 119

**110**of 119

**111**of 119

**112**of 119

**113**of 119

**114**of 119

**115**of 119

**116**of 119

**117**of 119

**118**of 119

**119**of 119

`bwareaopen`to remove the small "noise" objects detected.

## Recent Comments