我正在尝试在 matlab 中实现广义霍夫变换。该算法需要形状中每个点的梯度方向。如何测量如下图所示?
找到形状中一点的梯度方向
假设您使用离散输入并且 s(0..n-1) (或 Matlab 中的 s(1...n) )是沿二维形状边界的 x,y 点数组...
Gradient(i) = (s(i).x, s(i).y) - (s(i-1).x, s(i-1).y)
Amplitude(i) = sqrt(Gradient(i).x^2 + Gradient(i).y^2)
Angle(i) = atan(Gradient(i).y / Gradient(i).x)
为了让您在计算之前从 s 中的每个点减去 (Xc,Yc) 进行相对于 (Xc,Yc) 的计算。
如果您的计算是连续的,请将上述 s(i)-s(i-1) 替换为 limit(s)/limit(sigma) 并使用符号工具包。
如果通过一些轮廓跟踪对点进行排序或可以排序,那么上面建议的方法就可以了。但是,根据噪声和异常值,建议使用更大的支持区域,即该点的“左”/“右”N 个点,并使用可能带有先前异常值的线性回归拟合一条线到这些点-使用 RANSAC/MSAC 拒绝。得到的线法线表示估计/近似的梯度方向。当然,高阶多项式,即二次或三次,也可以用于拟合。
如果这些点未排序,则上述方法仍然可以通过蛮力搜索或通过合适的数据结构(例如 kd-trees)找到最近的邻居来使用。搜索半径取决于数据,但也可以动态调整。根据点的实际性质(分布、星座),最近邻搜索也可能允许执行轮廓跟踪,即沿轮廓(点序列)对点进行排序,见下文。
在任何情况下,对于未排序的点,只要形状/轮廓接近其自身,总是有可能产生歧义 - 特别是比轮廓上相邻点之间的距离更近。显然,最近邻搜索会拾取那些点,这些点在形状/轮廓方面并不是真正的邻居。更糟糕的是,除了上述所有情况外,还必须考虑轮廓交叉。交叉点处的梯度方向未定义。如上所述使用 RANSAC/MSAC 的稳健拟合可以通过获取异常值(如果存在“大量”)并重复稳健拟合步骤来帮助解决此类歧义和交叉检测,然后再决定。
只是按照上述思路提出的建议:
- 使用所有点的最近邻和多项式拟合计算近似梯度方向,保持每个点的拟合标准差。
- 找到轮廓上具有最小标准偏差的点。希望/假设这意味着它的所有最近邻居都是沿形状的实际邻居(?)。
- 使用最近邻、梯度方向和/或切线方向跟随轮廓,根据需要对梯度方向进行调整/校正。
本质上,最后一步的目的是增强梯度方向的局部平滑度,在适用的情况下,即不在交叉口等处。此外,最后一步有效地执行轮廓跟踪。最后,根据点坐标的范围,可以简单地将它们渲染成具有适当分辨率的二值图像,并直接使用基于图像的轮廓跟踪。这可能需要适当地缩放点并保持原始点和图像点之间的映射。此外,轮廓跟踪可能必须考虑重大差距,具体取决于数据。然而,之后点的连通性是已知的,并且基于邻居的近似变得相对简单。
希望有帮助,亲切的问候,德里克。