查找由区域掩码表示的多边形的角 [英] Find the corners of a polygon represented by a region mask

查看:696
本文介绍了查找由区域掩码表示的多边形的角的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述


BW = poly2mask(x,y,m,n)计算
二进制感兴趣区域
BW,来自ROI多边形,由向量x和y表示为
。 BW
的大小是m-by-n。



poly2mask 将BW
中位于多边形(X,Y)内的像素设置为1
并将多边形外的像素设置为
0。


问题:
给定一个凸四边形的二元掩码 BW ,确定四个角的最有效的方法是什么?



Eg,





到目前为止的最佳解决方案:
使用 edge 找到边界线,找到边缘图像中的4条线,然后找到这4条线的交叉点,或者在边缘图像上使用角度检测器。似乎很复杂,我不能帮助感觉有一个更简单的解决方案。



Btw, convhull 并不总是返回4分(也许有人可以建议 qhull

编辑: $ b

$ b Amro的回答似乎相当优雅和高效。但是每个角落可能有多个角,因为峰不是唯一的。我可以基于θ对它们进行聚类,并在一个真正的角落平均角,但主要的问题是使用 order(1:10)



10 足以记录所有角落,或者会排除真实角落的角落吗?

解决方案

这有点类似于 @AndyL 建议。但是我使用极坐标中的边界签名而不是切线。



请注意,我首先提取边,获取边界,然后将其转换为签名。最后,我们找到离质心最远的边界上的点,这些点构成找到的角。



以下是一个完整的实现:

  I = imread('oxyjj.png'); 
if ndims(I)== 3
I = rgb2gray(I);
end
subplot(221),imshow(I),title('org')

%%#Process Image
%#边缘检测
BW = edge(I,'sobel');
subplot(222),imshow(BW),title('edge')

%#dilation- erosion
se = strel
BW = imdilate(BW,se);
BW = imerode(BW,se);
subplot(223),imshow(BW),title('dilation-erosion')

%#fill holes
BW = imfill(BW,'holes');
subplot(224),imshow(BW),title('fill')

%#获取边界
B = bw边界(BW,8,'noholes');
B = B {1};

%%#boudary signature
%#将边界从笛卡尔坐标转换为阴影坐标
objB = bsxfun(@minus,B,mean(B)); $ b $bθ= cart2pol(objB(:,2),objB(:,1));

%#find corners
%#corners = find(diff(diff(rho)> 0)< 0); %#find peaks
[〜,order] = sort(rho,'descend');
corners = order(1:10);

%#plot边界签名+角
数字,绘图(theta,rho,'。'),保持
绘图(theta(corner),rho 'ro'),hold off
xlim([ - pi pi]),title('Boundary Signature'),xlabel('\theta'),ylabel('\rho')

%#plot image + corner
figure,imshow(BW),hold on
plot(B(corners,2),B(corners,1),'s','MarkerSize' 10,'MarkerFaceColor','r')
hold off,title('Corners')







EDIT:
回应雅各的评论,我应该解释,我第一次尝试找到签名中的峰值使用一/二导数,但最终取最远的N点。 10只是一个特别的价值,并将难以推广(我试过采取4相同的角数,但它没有涵盖所有的)。我认为聚集他们以删除重复的想法是值得研究的。



就我看来,第一种方法的问题是,如果绘制<$不考虑θ,您将得到不同的形状(不是相同的峰),因为速度我们跟踪的边界是不同的,取决于曲率。如果我们可以找出如何标准化这种效果,我们可以使用导数获得更准确的结果。


BW = poly2mask(x, y, m, n) computes a binary region of interest (ROI) mask, BW, from an ROI polygon, represented by the vectors x and y. The size of BW is m-by-n.

poly2mask sets pixels in BW that are inside the polygon (X,Y) to 1 and sets pixels outside the polygon to 0.

Problem: Given such a binary mask BW of a convex quadrilateral, what would be the most efficient way to determine the four corners?

E.g.,

Best Solution so far: Use edge to find the bounding lines, the Hough transform to find the 4 lines in the edge image and then find the intersection points of those 4 lines or use a corner detector on the edge image. Seems complicated, and I can't help feeling there's a simpler solution out there.

Btw, convhull doesn't always return 4 points (maybe someone can suggest qhull options to prevent that) : it returns a few points along the edges as well.

EDIT: Amro's answer seems quite elegant and efficient. But there could be multiple "corners" at each real corner since the peaks aren't unique. I could cluster them based on θ and average the "corners" around a real corner but the main problem is the use of order(1:10).

Is 10 enough to account for all the corners or will this exclude a "corner" at a real corner?

解决方案

This is somewhat similar to what @AndyL suggested. However I'm using the boundary signature in polar coordinates instead of the tangent.

Note that I start by extracting the edges, getting the boundary, then converting it to signature. Finally we find the points on the boundary that are furthest from the centroid, those points constitute the corners found. (Alternatively we can also detect peaks in the signature for corners).

The following is a complete implementation:

I = imread('oxyjj.png');
if ndims(I)==3
    I = rgb2gray(I);
end
subplot(221), imshow(I), title('org')

%%# Process Image
%# edge detection
BW = edge(I, 'sobel');
subplot(222), imshow(BW), title('edge')

%# dilation-erosion
se = strel('disk', 2);
BW = imdilate(BW,se);
BW = imerode(BW,se);
subplot(223), imshow(BW), title('dilation-erosion')

%# fill holes
BW = imfill(BW, 'holes');
subplot(224), imshow(BW), title('fill')

%# get boundary
B = bwboundaries(BW, 8, 'noholes');
B = B{1};

%%# boudary signature
%# convert boundary from cartesian to ploar coordinates
objB = bsxfun(@minus, B, mean(B));
[theta, rho] = cart2pol(objB(:,2), objB(:,1));

%# find corners
%#corners = find( diff(diff(rho)>0) < 0 );     %# find peaks
[~,order] = sort(rho, 'descend');
corners = order(1:10);

%# plot boundary signature + corners
figure, plot(theta, rho, '.'), hold on
plot(theta(corners), rho(corners), 'ro'), hold off
xlim([-pi pi]), title('Boundary Signature'), xlabel('\theta'), ylabel('\rho')

%# plot image + corners
figure, imshow(BW), hold on
plot(B(corners,2), B(corners,1), 's', 'MarkerSize',10, 'MarkerFaceColor','r')
hold off, title('Corners')


EDIT: In response to Jacob's comment, I should explain that I first tried to find the peaks in the signature using first/second derivatives, but ended up taking the furthest N-points. 10 was just an ad-hoc value, and would be difficult to generalize (I tried taking 4 same as number of corners, but it didn't cover all of them). I think the idea of clustering them to remove duplicates is worth looking into.

As far as I see it, the problem with the 1st approach was that if you plot rho without taking θ into account, you will get a different shape (not the same peaks), since the speed by which we trace the boundary is different and depends on the curvature. If we could figure out how to normalize that effect, we can get more accurate results using derivatives.

这篇关于查找由区域掩码表示的多边形的角的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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