从图像中分离连接的对象和单个对象

时间:2014-12-05 17:57:44

标签: matlab image-processing matlab-figure

我正在研究Matlab中的图像,如链接http://lyremjeni.files.wordpress.com/2013/08/tocleanblobs.jpg

所示

我想从图像中分离连接/分组的单元格blob和单个单元格blob,然后将它们显示在单独的图中。请建议我如何实现这种分离。

2 个答案:

答案 0 :(得分:4)

这里有两个你可以使用的解决方案,第一个使用bwconncomp找到二进制图像中的连接元素,第二个使用imfindcircles,相信它或不相信找到圆圈!因此,在要检测的对象不是所有圆圈的情况下,首选解决方案将是首选。

我更喜欢第一个,因为它区分单个圆圈和圆群,这就是你所问的,而使用imfindcircles的方法对于识别单个圆圈非常有用,因此不一定是聚类。这是代码:

1- bwconncomp

clear
close all
clc

A = imread('Circles.jpg');
BW = im2bw(A); %// Convert to binary with threshold of 0.5. 

CC = bwconncomp(BW); %// Find connected components.

这就是CC的样子,即具有几个字段的结构:

CC = 

    Connectivity: 8
       ImageSize: [256 256]
      NumObjects: 15
    PixelIdxList: {1x15 cell}

如您所见,检测到15个物体。

现在循环对象并绘制/绘制它们:

BW2 = zeros(size(BW)); %// Create dummy image for display purposes.
imshow(BW2)
hold on

for k = 1:CC.NumObjects %// Loop through each object and plot it in white. This is where you can create individual figures for each object.

    PixId = CC.PixelIdxList{k}; %// Just simpler to understand

    if size(PixId,1) ==1 %// If only one row, don't consider.        
        continue
    else
    BW2(PixId) = 255;
 %figure(k) %// Uncomment this if you want individual figures.
    imshow(BW2)
    pause(.5) %// Only for display purposes.
    end
end

如果你运行代码,你会发现它实际上只创建了一个数字;这仅用于演示,但如果你想要图中的每个对象,只需在我注意到创建一个的循环中添加figure

2- imfindcircles

这里的原理非常简单,因为算法检测圆并存储它们的半径和中心坐标。然后很容易绘制/裁剪它们以单独获取它们。正如我所说的那样,它并没有检测到圆形的簇,但我认为无论如何都要知道它。

在这里,我为每个检测到的圆创建一个数字。

A = imread('Circles.jpg');
[centers, radii, ~] = imfindcircles(A,[5 25],'Sensitivity',.95,'ObjectPolarity','bright');

A_crop = cell(1,numel(radii));
for k =1:numel(radii)    

%// Since imcrop requires a cropping rectangle, we need to fin the x and y coordinates of the lower-left corner, as well as the width and height of the rectangle. 
    x = centers(k,1);
    y = centers(k,2);
    r = radii(k);   
   A_crop{k} = imcrop(A,[x-r y-r 2*r 2*r]); %// [x y width height]
   imshow(A_crop) %// New figure
   pause(0.5) 
end

如果您想查看所有圆圈,可以使用:

imshow(A);
 hold on

 viscircles(centers, radii,'EdgeColor','b');
 hold off

给出以下内容:

enter image description here

答案 1 :(得分:0)

如果你想将单个blob与分组blob分开(这是我从你的问题中理解的),请尝试下面的代码。

基本上:

  • 使用固定阈值(0.5)对图像进行分割,因为图像只是黑/白

  • 查找已连接的组件

  • 计算每个连接组件的指标。指标为4*pi*area/perimeter^2。对于完美的圆形,此度量标准仅为1,对于任何其他形状,该度量标准小于1

  • 使用度量标准将单个blob与分组blob分开(单个blob将非常类似于圆圈,分组blob将不会)

<强>代码:

function[single, grouped] = ipl_separateblobs(I)

% I is assumed to be a grayscale image

% Step 1: Convert image from grayscale to binary
BW = im2bw(I); 

% Step 2: Find connected components
[L, n] = bwlabel(BW); 
stats = regionprops(L, 'Area', 'Perimeter', 'Image');

% Step 3: Separate objects (avoiding very small objects)
MIN_AREA = 10; 
MIN_CIRCLE_METRIC = 0.75; 
single= [];
index_s = 0;
grouped = [];
index_g = 0;

for i=1:n
    if(stats(i).Area >= MIN_AREA)
        metric = (4*pi*stats(i).Area)/(stats(i).Perimeter^2);
        if(metric >= MIN_CIRCLE_METRIC)            
            index_s = index_s + 1;            
            single{index_s, 1} = stats(i).Image;
            single{index_s, 2} = metric;                
        else
            index_g = index_g + 1;
            grouped{index_g, 1} = stats(i).Image;
            grouped{index_g, 2} = metric;                   
        end
    end
end

% Display original image
figure('Name', 'Original image');
imshow(I);

% Display single objects
figure('Name', 'Single blobs'); 
m = ceil(index_s/3); 
for i=1:index_s
    subplot(m, 3, i);
    imshow(single{i,1});
    title(['Metric: ' num2str(single{i,2})]);    
end

% Display grouped objects
figure('Name', 'Grouped blobs'); 
m  = ceil(index_g/3);
for i=1:index_g
    subplot(m, 3, i);
    imshow(grouped{i, 1});
    title(['Metric: ' num2str(grouped{i, 2})]);
end

end

您可能需要根据需要调整MIN_AREAMIN_CIRCLE_METRIC的值:

  • 将跳过面积小于MIN_AREA的已连接组件(以避免噪音)

  • 其度量大于或等于MIN_CIRCLE_METRIC的已连接组件被视为单个blob;否则它们被视为分组的blob。

请不要害怕对此有任何疑问。