# How to get cell boundaries in the image?

I have a microscope image of some animal tissue and wish to get the contours for all the cells that are present in the image. the cells are connected to the neighbouring cells via these contours. At the bottom of the image the signal intensity is faint but the human eye can still detect some contours.

I have tried a bunch of techniques including the use of ClusteringComponents and MorphologicalBinarize, LaplacianGaussianFilter and GradientFilter but have been unsuccessful in my approaches. The particular problem I am facing is the inability to get rid of the noisy signal (grains/granules whatever you may wish to call them) inside the contours during segmentation.

Can anyone kindly help me for my research problem. Thanks in advance.

the closest i have are the following approaches but they do not prove satisfactory:

KuwaharaFilter[CommonestFilter[GaussianFilter[
Binarize[img, 0.2, Method -> "MinimumError"], 3], 3],3]


Using SkeletonTransform after KuwaharaFilter and application of other filters

KuwaharaFilter[CommonestFilter[GaussianFilter[
Binarize[img, 0.18, Method -> "MinimumError"], 3],3], 3] //
Binarize[#, 0.6] & // SkeletonTransform


Using DistanceTransform in conjunction with KuwaharaFilter and a bunch of filters

KuwaharaFilter[CommonestFilter[GaussianFilter[
Binarize[img, 0.18, Method -> "MinimumError"], 3],3], 3] //
Binarize[#, 0.55] & //DistanceTransform // ImageAdjust


• It is always good idea to provide a link to a duplicate question on the Wolfram Community. It can help both current answerers and future visitors of the site. Oct 13 '16 at 17:06
• For reference, Shadi Ashnai provided an answer here. Oct 14 '16 at 21:34

img = Import["https://i.stack.imgur.com/YsIVf.png"];

img2 = Pruning @ Thinning @ Closing[#, 10]& @ DeleteSmallComponents[#, 25000]& @
LocalAdaptiveBinarize[#, 50]& @ GaussianFilter[#, 10]& @ img


HighlightImage[img, img2]


• thanks. nice job ! but do you see the large region at the bottom right. there is still some segmentation that can be done there. somehow its missing that Oct 13 '16 at 11:50
• and also i see two more places where segmentation is missing Oct 13 '16 at 11:52
• Citing nikie: "If you start with noisy data, you should always expect somewhat noisy results". The upper right part of the image is the sharpest. Image processing algorithms tend to treat an image as a whole - if they work well on a part that is sharp, they usually fail where the quality is lower. You can, e.g., apply ImageAdjust to img first, change the parameter in GaussianFilter from 10 to 12, but is that really a better result?... Oct 13 '16 at 13:20
• ...You could also divide the image in two parts and process them separately. Oct 13 '16 at 13:20

I have somewhat mixed corey's and nikie's approach (check their posts) to arrive at a somewhat reasonable segmentation. Kudos to them.

img2 =  ImageAdjust@RidgeFilter[img, 5] // GaussianFilter[#, 8] & //
DeleteSmallComponents[#, 25000] & // Closing[#, 10] & //
Thinning // Pruning;

HighlightImage[img, img2]


Your image contains thin, line-like structures, so a RidgeFilter seems like a good idea:

img = Import["https://i.stack.imgur.com/YsIVf.png"]


Die ridges have large brightness variance, but MorphologicalBinarize works well enough:

bin = MorphologicalBinarize[ridges, {.1, .5}]


To segment the individual cells, I need markers for each cell center. The maxima of a distance transform usually give good markers:

dist = DistanceTransform[ColorNegate@bin];
maxMarkers = MaxDetect[dist, 2];
HighlightImage[bin, maxMarkers]


Now I can use those markers as starting points for a watershed segmentation:

watersheds = WatershedComponents[ridges, maxMarkers];
Colorize[watersheds]


These are segmentation borders highlighted in the original image:

HighlightImage[img, ColorNegate[Binarize[Image[watersheds]]]]


• great. there are some extraneous cells (extra) that are formed as a result of this Oct 13 '16 at 11:54
• Yes. Cleaning those up is left as an exercise to the reader ;-) Oct 13 '16 at 12:22
• haha .. just saying that there should be no need to clean up. Because cleaning could change the topology of the mask. Removing something that was not there to begin with and is shared between three bodies can change topology in three different ways ! Oct 13 '16 at 12:27
• @AliHashmi: If you start with noisy data, you should always expect somewhat noisy results. Regarding extra segments: WatershedComponents (actually, all segmentation algorithms) try to segment the whole image. There is not enough data in your image to do that, so the visible borders are "extrapolated" to the border of the image. If you don't want that, use DeleteBorderComponents on the segmentation result. For the interior areas, you might want to clean up the markers image - but that's really something you have to do yourself, as you're the one who knows what you're looking for Oct 13 '16 at 12:40

I provide a method don't include DeleteSmallComponents

pic = Import["https://i.stack.imgur.com/YsIVf.png"]

HighlightImage[pic,
ColorNegate@