Matlab:单独的连接组件 [英] Matlab: separate connected components

查看:182
本文介绍了Matlab:单独的连接组件的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在处理我的图像处理问题并检测硬币。



我在这里有一些像这样的图像:



并初始化所有ID数组与图像大小相同的零。接下来,对于每个圆的每对半径和中心,我们定义一个以此点为中心的圆,该圆向外延伸给定半径。然后,我们将它们用作ID数组中的位置,并将其设置为该特定圆的唯一ID。 ID 的结果将类似于我们终于展示了图片。



这就是我们得到的:




I was working on my image processing problem with detecting coins.

I have some images like this one here:

http://dennlinger.bplaced.net/t06-4.jpg

and wanted to separate the falsely connected coins.

We already tried the watershed method as stated on the MATLAB-Homepage:

especially since the first example is exactly our problem.

But instead we get a somehow very messed up separation as you can see here:

http://dennlinger.bplaced.net/myAwesomeTry.PNG

We already extracted the area of the coin using the regionprops Extrema parameter and casting the watershed only on the needed area.

I'd appreciate any help with the problem or even another method of getting it separated.

解决方案

If you have the Image Processing Toolbox, I can also suggest the Circular Hough Transform through imfindcircles. However, this requires at least version R2012a, so if you don't have it, this won't work.

For the sake of completeness, I'll assume you have it. This is a good method if you want to leave the image untouched. If you don't know what the Hough Transform is, it is a method for finding straight lines in an image. The circular Hough Transform is a special case that aims to find circles in the image.

The added advantage of the circular Hough Transform is that it is able to detect partial circles in an image. This means that those regions in your image that are connected, we can detect them as separate circles. How you'd call imfindcircles is in the following fashion:

[centers,radii] = imfindcircles(A, radiusRange);

A would be your binary image of objects, and radiusRange is a two-element array that specifies the minimum and maximum radii of the circles you want to detect in your image. The outputs are:

  • centers: A N x 2 array that tells you the (x,y) co-ordinates of each centre of a circle that is detected in the image - x being the column and y being the row.
  • radii: For each corresponding centre detected, this also gives the radius of each circle detected. This is a N x 1 array.

There are additional parameters to imfindcircles that you may find useful, such as the Sensitivity. A higher sensitivity means that it is able to detect circular shapes that are more non-uniform, such as what you are showing in your image. They aren't perfect circles, but they are round shapes. The default sensitivity is 0.85. I set it to 0.9 to get good results. Also, playing around with your image, I found that the radii ranged from 50 pixels to 150 pixels. Therefore, I did this:

im = im2bw(imread('http://dennlinger.bplaced.net/t06-4.jpg'));
[centers,radii] = imfindcircles(im, [50 150], 'Sensitivity', 0.9);

The first line of code reads in your image directly from StackOverflow. I also convert this to logical or true black and white as the image you uploaded is of type uint8. This image is stored in im. Next, we call imfindcircles in the method that we described.

Now, if we want to visualize the detected circles, simply use imshow to show your image, then use the viscircles to draw the circles in the image.

imshow(im);
viscircles(centers, radii, 'DrawBackgroundCircle', false);

viscircles by default draws the circles with a white background over the contour. I want to disable this because your image has white circles and I don't want to show false contouring. This is what I get with the above code:

Therefore, what you can take away from this is the centers and radii variables. centers will give you the centre of each detected circle while radii will tell you what the radii is for each circle.


Now, if you want to simulate what regionprops is doing, we can iterate through all of the detected circles and physically draw them onto a 2D map where each circle would be labeled by an ID number. As such, we can do something like this:

[X,Y] = meshgrid(1:size(im,2), 1:size(im,1));
IDs = zeros(size(im));
for idx = 1 : numel(radii)
    r = radii(idx);
    cen = centers(idx,:);

    loc = (X - cen(1)).^2 + (Y - cen(2)).^2 <= r^2;
    IDs(loc) = idx;
end

We first define a rectangular grid of points using meshgrid and initialize an IDs array of all zeroes that is the same size as the image. Next, for each pair of radii and centres for each circle, we define a circle that is centered at this point that extends out for the given radius. We then use these as locations into the IDs array and set it to a unique ID for that particular circle. The result of IDs will be that which resembles the output of bwlabel. As such, if you want to extract the locations of where the idx circle is, you would do:

cir = IDs == idx;

For demonstration purposes, this is what the IDs array looks like once we scale the IDs such that it fits within a [0-255] range for visibility:

imshow(IDs, []);

Therefore, each shaded circle of a different shade of gray denotes a unique circle that was detected with imfindcircles.

However, the shades of gray are probably a bit ambiguous for certain coins as this blends into the background. Another way that we could visualize this is to apply a different colour map to the IDs array. We can try using the cool colour map, with the total number of colours to be the number of unique circles + 1 for the background. Therefore, we can do something like this:

cmap = cool(numel(radii) + 1);
RGB = ind2rgb(IDs, cmap);
imshow(RGB);

The above code will create a colour map such that each circle gets mapped to a unique colour in the cool colour map. The next line applies a mapping where each ID gets associated with a colour with ind2rgb and we finally show the image.

This is what we get:

这篇关于Matlab:单独的连接组件的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆