将最佳多边形拟合到离散轮廓
我很惊讶为什么没有人提到著名的Douglas Peucker 算法来简化折线。由于您手头有轮廓点,因此您可以直接从中受益。OpenCV 中的轮廓近似使用这种方法。请参阅此处了解用法,您还可以在此处或此处找到 MATLAB 实现。
霍夫变换是一种用于提取图像特征的图像处理算法。该算法的经典版本旨在从二进制图像中提取线条(例如this)。
有了这样做的能力,您就可以相当容易地编写脚本。这是在 Matlab 中使用霍夫变换(和相关实用程序)的一个。它可能需要图像处理工具箱,但希望你能找到它。
此代码中存在的唯一快捷方式是我告诉“houghpeaks”函数搜索 4 行。通过在霍夫空间中执行其他峰值检测方法,您可以比这更聪明(如果您不熟悉霍夫变换的输出,请阅读 wiki,https://en.wikipedia.org/wiki/Hough_transform)。
一个警告是霍夫变换只会给你整行。您必须对它们进行后处理才能获得线段。由于输入是一个凸多边形,其顶点位于/靠近图像的边缘,因此此示例在没有任何这些的情况下效果特别好。
clear all
close all
clc
% Load image (I suspect your input may be different, but the same ideas hold)
img = imread('polygon.png');
% Make a black/white image using the "blue" as the new white values
bw = img(:,:,1) ~= 255;
% Use hough transform to find lines
[H,theta,rho] = hough(bw);
P = houghpeaks(H,4);
lines = houghlines(bw,theta,rho,P);
% Visualization
imagesc(bw); colormap gray;
hold on;
for l = 1:length(lines)
plot([lines(l).point1(1) lines(l).point2(1)], ...
[lines(l).point1(2) lines(l).point2(2)],'r');
end
有一种使用离散几何概念的方法:离散几何是一门学科,它处理定义为试图模仿其标准对应物的像素集的对象。它定义了离散段、离散圆、离散平面等......在你的情况下,有一个算法 [1] 定义了离散段是什么,并且在输入图像中重建了最大段的集合,即无法通过向其添加新像素来进一步扩展的片段。另见模糊数据的扩展[2,3]。该方法成功地应用于多视图图像的 3D 重建 [4]
[1] I. DEBLED-Rennesson, J.-P. REVEILLES,数字曲线分割的线性算法,国际模式识别和人工智能杂志,第 9 卷,第 6 期,1995 年 12 月。
[2] I. DEBLED-Rennesson,J.-L。REMY 和 J. ROUYER-DEGLI,将离散曲线线性分割成模糊段,离散应用数学,151:122-137,2005 年 10 月。
[3] I. DEBLED-Rennesson、F. FESCHET 和 J. ROUYER-DEGLI,线性时间噪声形状的最佳模糊分段分解,计算机与图形,30(1),2006。
我不会说它简单,但本文提供了数据与多边形的最小二乘拟合。如果您正在寻找准确性,这可能是最佳选择。
https://www.researchgate.net/publication/303329343_Least-squares_Fitting_of_Polygons
主动形状模型是这种场景的巧妙算法。
另一种方法是将其分解为 4 个单独的线性回归问题。你有尖角,所以创建一个点数组,应用基本的平滑算法,并查看每个点与其邻居的斜率(即导数)。或者,如果您没有尖角,请拟合 catmull-rom 样条曲线(boost c++ 库对此进行了实现)并遍历样条曲线,查看导数以确定分割点。
如果您正在寻找简单快速的方法,我同意 Douglas Peuker 算法,但它需要针对您尝试拟合的数据集进行调整,否则它可能会在错误的线段上拾取角点,从而允许不需要的错误。您可以使用使用多个阈值的迭代方法,测量误差,并尝试在误差最小的点之间进行更精细的迭代。
如评论中所述,霍夫变换和凸包/凸缺陷在 OpenCV 中具有易于使用的实现,并且可能也有帮助。
