分割灰度图像

7
我在实现灰度图像的正确分割上遇到了问题:
期望的分割结果如下图所示:
我最感兴趣的是圆圈内的三个组件。因此,正如您所看到的,我希望将顶部图像分割成三个组件:两个半圆和它们之间的矩形。
我尝试了各种膨胀、腐蚀和重建的组合,以及各种聚类算法,包括k均值、isodata和高斯混合模型——都有不同程度的成功。
如果您有任何建议,将不胜感激。
编辑:这是我能够获得的最佳结果。这是使用主动轮廓对圆形ROI进行分割,然后应用isodata聚类获得的:
但是有两个问题:
1.属于左上角聚类的右下角聚类周围的白色光晕
2.属于中心聚类的右上角和左下角聚类周围的灰色光晕。

看起来你有一个三峰直方图。请查看我在dsp.stackexchange.com上的答案-> http://dsp.stackexchange.com/questions/3643/image-segmentation-issue-of-different-materials/3650#3650。无论如何,你的问题应该移动到那个网站。 - Andrey Rubshtein
我尝试过基于直方图的分割。这种方法的问题在于,右侧聚类周围的像素值最接近左侧聚类的像素,导致右侧聚类周围出现“光环”。 - Richard
你尝试过使用bwboundaries或bwlabel吗?它们可能适合你。但是,如果光晕效果太强,你可能无法得到想要的结果。不过,通过一些前后的操作和清理,你可能会得到想要的结果。使用类似hough circles这样的东西,或者像这个方法一样的其他方法,可以帮助你知道圆的边界。 - Bill
我本应该最初就提到这一点,但我使用主动轮廓来分割圆形ROI。我已经在我的问题中更新了结果的图片。我不确定bwboundaries和bwlabel如何帮助这里,因为它们需要一个二进制图像。 - Richard
2个回答

7

这是一个入门级的技术问题... 使用圆形霍夫变换来寻找圆形部分。为此,我会首先在图像上进行局部阈值处理

 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.');

在圆圈内选择:

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

编辑:

要开始阈值图像并通过查看直方图,找到第一个局部极大值并循环迭代直到找到2个分离的段,使用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

现在可以通过从圆中取出两个标记部分来获得中间部分,剩下的就是中间部分(+一些光晕)。

 bw2=(bw<1.*f);

但是在进行了一些中值滤波之后,我们得到了更加合理的结果。
 bw2= medfilt2(medfilt2(bw2));

我们一起得到:

 imagesc(bw+3*bw2); 

这里输入图片描述

最后一部分是真正的“粗略方法”,我相信您已经使用的工具将带来更好的结果...


非常好,感谢您抽出时间来完成这个。然而,结果严重依赖于阈值,例如在这种情况下是186。例如,183的值会显著扭曲结果。我意识到我没有在我的问题中指定这一点,但这只是问题的典型例子;还有许多其他需要类似分割的图像。因此,我希望能够提出一个自动化的通用解决方案。也许有一种方法可以“猜测”阈值参数。 - Richard
有几种方法可以做到这一点,请参见我的编辑,以了解一种快速而简单的方法,可以自动设置一个接近我之前所设定阈值的阈值... - bla

1

使用分水岭变换也可以得到一个近似的结果。这是反转图像上的分水岭 -> 分水岭(255-I) 这里是一个示例结果:

enter image description here

另一种简单的方法是使用圆形结构元素对原始图像进行形态学闭合(可以对颗粒度进行多尺度闭合),然后获取完整的圆。之后提取圆和其中的组件更容易。
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


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接