这与
@AndyL建议的有些相似.但是我在极坐标中使用边界签名而不是切线.
请注意,我首先提取边缘,获取边界,然后将其转换为签名.最后,我们发现边界上距离质心最远的点,这些点构成了找到的角点. (或者我们也可以检测角落签名中的峰值).
以下是一个完整的实现:
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')
编辑:
在回应雅各布的评论时,我应该解释一下,我首先尝试使用一阶/二阶导数找到签名中的峰值,但最终得到了最远的N点. 10只是一个临时值,并且很难概括(我尝试将4个与角数相同,但它并未涵盖所有这些).我认为将它们聚类以删除重复的想法值得研究.
据我所知,第一种方法的问题是,如果你在不考虑θ的情况下绘制rho,你会得到一个不同的形状(不是相同的峰值),因为我们追踪边界的速度是不同的,取决于曲率.如果我们能够弄清楚如何规范化这种效应,我们可以使用衍生物获得更准确的结果.