16
$\begingroup$

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.

enter image description here

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]

enter image description here

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

enter image description here

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

enter image description here

$\endgroup$
2
  • 3
    $\begingroup$ 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. $\endgroup$ Oct 13, 2016 at 17:06
  • 4
    $\begingroup$ For reference, Shadi Ashnai provided an answer here. $\endgroup$ Oct 14, 2016 at 21:34

4 Answers 4

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

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

enter image description here

HighlightImage[img, img2]

enter image description here

$\endgroup$
4
  • $\begingroup$ 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 $\endgroup$
    – Ali Hashmi
    Oct 13, 2016 at 11:50
  • $\begingroup$ and also i see two more places where segmentation is missing $\endgroup$
    – Ali Hashmi
    Oct 13, 2016 at 11:52
  • 4
    $\begingroup$ 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?... $\endgroup$
    – corey979
    Oct 13, 2016 at 13:20
  • $\begingroup$ ...You could also divide the image in two parts and process them separately. $\endgroup$
    – corey979
    Oct 13, 2016 at 13:20
13
$\begingroup$

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] & // 
   LocalAdaptiveBinarize[#, 50] & // 
  DeleteSmallComponents[#, 25000] & // Closing[#, 10] & // 
Thinning // Pruning;

HighlightImage[img, img2]

enter image description here

$\endgroup$
0
12
$\begingroup$

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

img = Import["https://i.stack.imgur.com/YsIVf.png"]
ridges = ImageAdjust[RidgeFilter[img, 5]]

enter image description here

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

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

enter image description here

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]

enter image description here

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

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

enter image description here

These are segmentation borders highlighted in the original image:

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

enter image description here

$\endgroup$
4
  • $\begingroup$ great. there are some extraneous cells (extra) that are formed as a result of this $\endgroup$
    – Ali Hashmi
    Oct 13, 2016 at 11:54
  • $\begingroup$ Yes. Cleaning those up is left as an exercise to the reader ;-) $\endgroup$ Oct 13, 2016 at 12:22
  • $\begingroup$ 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 ! $\endgroup$
    – Ali Hashmi
    Oct 13, 2016 at 12:27
  • 2
    $\begingroup$ @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 $\endgroup$ Oct 13, 2016 at 12:40
4
$\begingroup$

I provide a method don't include DeleteSmallComponents

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

HighlightImage[pic, 
 ColorNegate@
  Image[WatershedComponents[GradientFilter[MeanFilter[pic, 5], 2], 
    MaxDetect[
     ImageAdjust@
      DistanceTransform[
       ColorNegate[Binarize[MeanFilter[pic, 8], .2]]], .1]]]]

$\endgroup$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.