【问题标题】:Segmenting a grayscale image分割灰度图像
【发布时间】:2012-11-04 09:03:50
【问题描述】:

我无法正确分割灰度图像:

基本事实,即我希望分割的样子是这样的:

我最感兴趣的是圈内的三个组成部分。因此,如您所见,我想将顶部图像分割成三个部分:两个半圆和它们之间的一个矩形。

我尝试了膨胀、腐蚀和重建的各种组合,以及各种聚类算法,包括 k-means、isodata 和高斯混合——所有这些都取得了不同程度的成功。

任何建议将不胜感激。

编辑:这是我能够获得的最佳结果。这是使用活动轮廓分割圆形 ROI,然后应用 isodata 聚类获得的:

这样做有两个问题:

  • 右下角星团周围的白色光晕,属于左上角星团
  • 右上和左下星团周围的灰色光晕,属于中心星团。

【问题讨论】:

  • 看起来你有一个三模态直方图。在 dsp.stackexchange.com -> dsp.stackexchange.com/questions/3643/… 上查看我的答案。在任何情况下,您的问题都应该移至该网站。
  • 我尝试过基于直方图的分割。这种方法的问题在于,最右边簇周围的像素值与最左边簇的像素最相似,导致最右边簇周围出现“光晕”。
  • 您尝试过 bwboundaries 或 bwlabel 吗?他们可能会为你工作。但如果光环效应太大,你可能得不到你想要的结果。尽管如此,通过前后的一些操作和清洁,你可能会得到你想要的。使用hough circles 之类的方法或this one 之类的其他方法也可能会有所帮助,以便您了解圈子的范围。
  • 我本来应该提到这一点,但我使用活动轮廓来分割圆形 ROI。我已经用结果图片更新了我的问题。我不确定 bwboundaries 和 bwlabel 在这里有什么帮助,因为它们需要二进制图像。

标签: matlab image-processing image-segmentation morphological-analysis mathematical-morphology


【解决方案1】:

这是一个首发... 使用circular Hough transform 查找圆形部分。为此,我最初threshold the image locally

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

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

 bw2=(bw<1.*f);

但经过一些中值过滤后,我们会得到更合理的结果

 bw2= medfilt2(medfilt2(bw2));

我们一起得到:

 imagesc(bw+3*bw2); 

最后一部分是真正的“又快又脏”,我相信用你已经用过的工具你会得到更好的结果...

【讨论】:

  • 非常好,感谢您花时间提出这个问题。但是,结果很大程度上取决于阈值,在本例中为 186。例如,值 183 会显着扭曲结果。我意识到我没有在我的问题中指定这一点,但这只是问题的一个典型示例;还有许多其他图像需要类似的分割。因此,我希望提出一个自动化的通用解决方案。也许有一些方法可以“猜测”阈值参数。
  • 有几种方法可以做到这一点,请参阅我的编辑以快速一种肮脏的方式来自动设置与我之前的阈值不远的阈值......
【解决方案2】:

也可以使用watershed transformation 获得近似结果。这是倒置图像上的分水岭 -> watershed(255-I) 这是一个示例结果:

另一种简单的方法是使用圆盘结构元素对原始图像进行形态闭合(可以对粒度进行多尺度闭合),然后获得完整的圆。在此之后提取圆和组件更容易。

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

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2021-05-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-04-14
    • 2015-03-03
    • 2022-10-17
    相关资源
    最近更新 更多