I have a digital image from X-ray tomography as below: enter image description here

There are three different ingredients/components to be segmented:

  1. the continuous phase, mastics;
  2. the discrete phase I, aggregates;
  3. the discrete phase II, voids

which are all visually legible though the contrast is low:

enter image description here

I tried several approaches for segmentation, and the currently best result is only like this:



cellEdges=GradientFilter[ImageAdjust[img], 2]//ImageAdjust//Binarize;

voids = Closing[cellEdges, 3]

enter image description here

2.aggregates and mastics,

agg01=ImageFilter[Mean[Flatten[#]]&,LocalAdaptiveBinarize[img, 15],2];
agg02=GeodesicOpening[agg01, 5];
agg03=GeodesicOpening[agg02, 5]

The obtained discrete phase of aggregates looks continuous especially on the edge of the circular region; aggregates should be isolated islands with no black dots expected on them, but the current segmentation does not seem to achieve this.

Such a segmentation differs significantly from its visual inspection. How can I improve it?

enter image description here


1 Answer 1


I'm not sure if this is any improvement at all, but maybe it will at least serve as a hint on other approaches that might work in a desired way.

I'm creating 7 images, so I'll display only the final one here. You might want to look at the intermediate steps as well.

img = ImageCrop @ Import["https://i.sstatic.net/9q5QX.png"]
ImageHistogram @ img

enter image description here

Black corresponds to zero, and we see that there are two main peaks at around 0.55 and 0.75. Unfortunately, the overlap is so strong that we cannot simply filter out the low-intensity pixels. Instead

img2 = GaussianFilter[#, 1] &@ImageAdjust@ColorToneMapping[#, 0.5] &@img

which has

ImageHistogram @ img2

enter image description here

from which I choose 0.96 for

img3 = Binarize[img2, 0.96, Method -> "MinimumError"]
img4 = GaussianFilter[#, 3] &@img3
img5 = CommonestFilter[#, 3] &@img4
img6 = KuwaharaFilter[#, 3] &@img5
img7 = Closing[#, 1] & @ LocalAdaptiveBinarize[img6, 20]
img8 = FillingTransform@
    DeleteSmallComponents[#, 55, Method -> "Mean"] &@img7

enter image description here

(You can also use DeleteSmallComponents[#, 200] & on img8.)

Certainly not perfect as some features look rather bad (e.g., the big rapezoidal island in the bottom part is destroyed, and the big black stain completely surrounded by white in the upper right part), but several of them are very accurate, and the features near the edges are separated better.

The thing is, that the features in the middle are quite well separated, while those near the edges are tightly clustered. In such a situation maybe the initial img should be divided into two parts - the inner circle and the outer ring - and processed separately, with different parameters of the functions applied, and joined at the end.

  • $\begingroup$ Thank you! Actually, I have got a series of such low contrast digital images of nearly 1000 slicers. That's why I prefer batch segmentation via Mathematica/Python/Matlab scripts. However, it seems there is no simple method to obtain as good results as those by hand. $\endgroup$ Commented Sep 30, 2016 at 5:11

Your Answer

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

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