OpenCV函数convexityDefects()
中用于计算轮廓的凸度缺陷的算法是什么?
请描述和说明算法的高级操作及其输入和输出。
答案 0 :(得分:3)
基于documentation,输入是两个坐标列表:
contour
定义原始轮廓(下图为红色)convexhull
定义了与该轮廓相对应的凸包(下图为蓝色)algorithm的工作方式如下:
如果轮廓或船体包含的点少于3个,则轮廓始终为凸形,不需要进行更多处理。该算法可确保以相同的方向访问轮廓和船体。
NB: 在进一步的解释中,我假设它们的方向相同,并且忽略了有关将浮点深度表示为整数的详细信息。 / em>
然后对于定义凸包的一个边缘的每对相邻船体点(H[i]
,H[i+1]
),计算轮廓C[n]
上每个点到边缘的距离位于H[i]
和H[i+1]
之间(不包括C[n] == H[i+1]
)。如果距离大于零,则存在缺陷。如果存在缺陷,则记录i
,i+1
,最大距离和最大位置所在的轮廓点的索引(n
)。
距离的计算方法如下:
dx0 = H[i+1].x - H[i].x
dy0 = H[i+1].y - H[i].y
if (dx0 is 0) and (dy0 is 0) then
scale = 0
else
scale = 1 / sqrt(dx0 * dx0 + dy0 * dy0)
dx = C[n].x - H[i].x
dy = C[n].y - H[i].y
distance = abs(-dy0 * dx + dx0 * dy) * scale
就矢量而言,可视化可能更容易:
C
:从H[i]
到C[n]
H
:从H[i]
到H[i+1]
H_rot
:船体边缘矢量 H
旋转了90度U_rot
:方向为 H_rot
H
的分量是[dx0, dy0]
,所以旋转90度将得到[-dy0, dx0]
。
scale
用于从 U_rot
中查找 H_rot
,但是由于除法运算的计算开销比乘法大,因此求逆用作优化。还应在C[n]
循环之前进行预先计算,以免重新计算每次迭代。
| H
| = sqrt(dx0 * dx0 + dy0 * dy0)
U_rot
= H_rot
/ | H
| = H_rot
* scale
然后, C
和 U_rot
之间的点积给出了缺陷点到船体边缘的垂直距离,以及{{ 1}}用于在任何方向上获得正值。
距离= abs( abs()
。 U_rot
)= abs(-dy0 * dx + dx0 * dy)*比例
在上图所示的场景中,在第一次迭代中,边缘由C
和H[0]
定义。检查该边缘的轮廓点是H[1]
,C[0]
和C[1]
(自C[2]
起)。
C[3] == H[1]
和C[1]
处存在缺陷。 C[2]
处的缺陷最深,因此算法将记录C[1]
。
下一条边由(0, 1, 1, 50)
和H[1]
以及相应的轮廓点H[2]
定义。没有缺陷,因此没有任何记录。
下一条边由C[3]
和H[2]
以及相应的轮廓点H[3]
定义。没有缺陷,因此没有任何记录。
自C[4]
起,最后一个轮廓点可以忽略-那里没有缺陷。