问题描述
问题:
给定一个凸四边形的二元掩码 BW
,确定四个角的最有效的方法是什么?
Eg,
到目前为止的最佳解决方案:
使用 edge
找到边界线,找到边缘图像中的4条线,然后找到这4条线的交叉点,或者在边缘图像上使用角度检测器。似乎很复杂,我不能帮助感觉有一个更简单的解决方案。
Btw, convhull
并不总是返回4分(也许有人可以建议 qhull
order(1:10)
。 10
足以记录所有角落,或者会排除真实角落的角落吗?
这有点类似于建议。但是我使用极坐标中的边界签名而不是切线。
请注意,我首先提取边,获取边界,然后将其转换为签名。最后,我们找到离质心最远的边界上的点,这些点构成找到的角。
以下是一个完整的实现:
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相同的角数,但它没有涵盖所有的)。我认为聚集他们以删除重复的想法是值得研究的。
就我看来,第一种方法的问题是,如果绘制<$不考虑θ
,您将得到不同的形状(不是相同的峰),因为速度我们跟踪的边界是不同的,取决于曲率。如果我们可以找出如何标准化这种效果,我们可以使用导数获得更准确的结果。
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.
这篇关于查找由区域掩码表示的多边形的角的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!