6

我无法实现灰度图像的正确分割:细分的灰度图像

Image to be segmented

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

Ground truth

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

我已经尝试过扩张,侵蚀和重建的各种组合,以及各种聚类算法,包括k-means,isodata和高斯混合物 - 所有这些都取得了不同程度的成功。

任何建议,将不胜感激。

编辑:这是我已经能够获得最好的结果。这是使用主动轮廓来分割圆形ROI,然后应用ISODATA聚类得到:

Clusters

有两个问题与此:

  • 白色卤代右下簇周围,属于左上角群集
  • 围绕属于中心群集的右上角和左下角群集的灰色晕圈。
+0

它看起来像你有三峰直方图。查看我在dsp.stackexchange.com上的答案 - > http://dsp.stackexchange.com/questions/3643/image-segmentation-issue-of-different-materials/3650#3650。无论如何,你的问题应该被移到该网站。 –

+0

我试过基于直方图的分割。这种方法的问题在于,最右侧群集周围的像素值与最左侧群集的像素最相似,导致最右侧群集周围出现“晕圈”。 – Richard

+0

你有没有试过bwboundaries,或者bwlabel?他们可能会为你工作。但是如果光环效应太大,你可能得不到你想要的结果。尽管如此,通过一些操作和清理之前和之后,你可能会得到你想要的。它也可能有助于使用像[hough circles](http://www.mathworks.com/matlabcentral/fileexchange/26978-hough-transform-for-circles/content/html/circle_houghdemo.html)或其他方法[这一个](http://blogs.mathworks。com/pick/2008/05/23/detected-circles-in-an-image /),以便你知道你的圈子的界限。 – Bill

回答

7

这是首发... 使用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.'); 

enter image description here

只选择有什么圈内:

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

enter image description here

最后一部分是真正的“快速和肮脏的”,我敢肯定,随着这些工具,你已经使用过,你会得到更好的结果...

+0

非常好,谢谢你花时间想出这个。然而,结果在很大程度上取决于阈值,在这种情况下是186.例如,值183会显着扭曲结果。我意识到我没有在我的问题中指出这一点,但这只是这个问题的一个典型例子。还有许多其他需要类似分割的图像。因此,我希望能够提出一种自动化的通用解决方案。也许有一些方法来“猜测”阈值参数。 – Richard

+0

有几种方法可以做到这一点,请参阅我的编辑快速肮脏的方式来自动设置一个阈值,这是一个不同于我以前的... – bla

1

也可以使用watershed transformation获得近似结果。这是反相图像上的分水岭 - >分水岭(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