Grayscale image segmentation

I am having trouble getting the correct grayscale image segmentation:

Image to be segmented

The fundamental truth, that is, what we would like for this segmentation to look like this:

Ground truth

What interests me most is the three components within the circle. Thus, as you can see, I would like to segment the top image into three components: two semicircles and a rectangle between them.

I tried various combinations of dilatation, erosion and reconstruction, as well as various clustering algorithms, including k-means, isodate and a mixture of Gaussian - all with varying degrees of success.

Any suggestions would be appreciated.

Edit: here is the best result I could get. This was obtained using the active loop to segment the circular ROI and then apply isodata clustering:

Clusters

There are two problems with this:

  • A white halo around the lower right cluster, belonging to the upper left cluster
  • A gray halo around the upper and lower left clusters belonging to the central cluster.
+6
source share
2 answers

Here's the starter ... use the Hough circular transform to find the circular part. To do this, I initially generated a local image .

im=rgb2gray(imread('Ly7C8.png')); imbw = thresholdLocally(im,[2 2]); % thresold localy with a 2x2 window % preparing to find the circle props = regionprops(imbw,'Area','PixelIdxList','MajorAxisLength','MinorAxisLength'); [~,indexOfMax] = max([props.Area]); approximateRadius = props(indexOfMax).MajorAxisLength/2; radius=round(approximateRadius);%-1:approximateRadius+1); %find the circle using Hough trans. h = circle_hough(edge(imbw), radius,'same'); [~,maxIndex] = max(h(:)); [i,j,k] = ind2sub(size(h), maxIndex); center.x = j; center.y = i; figure;imagesc(im);imellipse(gca,[center.x-radius center.y-radius 2*radius 2*radius]); title('Finding the circle using Hough Trans.'); 

enter image description here

select only what is inside the circle:

  [y,x] = meshgrid(1:size(im,2),1:size(im,1)); z = (xj).^2+(yi).^2; f = (z<=radius^2); im=im.*uint8(f); 

EDIT:

find a place to start the image threshold to segment it by looking at the histogram, finding the first local maxima and iterating from there until 2 separate segments are found using bwlabel:

  p=hist(im(im>0),1:255); p=smooth(p,5); [pks,locs] = findpeaks(p); bw=bwlabel(im>locs(1)); i=0; while numel(unique(bw))<3 bw=bwlabel(im>locs(1)+i); i=i+1; end imagesc(bw); 

enter image description here

The middle part can now be obtained by removing two marked parts from the circle, and the remaining part will be the middle part (+ part of the halo)

  bw2=(bw<1.*f); 

but after some median filtering we get something more reasonable

  bw2= medfilt2(medfilt2(bw2)); 

and together we get:

  imagesc(bw+3*bw2); 

enter image description here

The last part is the real β€œquick and dirty" one, I’m sure that with the help of already used tools you will get better results ...

+7
source

You can also get an approximate result using the conversion of watersheds . This is the watershed in the inverted image β†’ the watershed (255-I). Here is an example:

enter image description here

Another simple method is to perform morphological closure of the original image using the disk structuring element (you can perform multiscale closure for granulometry), and then get a full circle. After that, removing the circle and lightening the components.

 se = strel('disk',3); Iclo = imclose(I, se);% This closes open circular cells. Ithresh = Iclo>170;% one can locate this threshold automatically by histogram modes (if you know apriori your cell structure.) Icircle = bwareaopen(Ithresh, 50); %to remove small noise components in the bg 

enter image description here

 Ithresh2 = I>185; % This again needs a simple histogram. 

enter image description here

+1
source

All Articles