OpenCV如何计算凸性缺陷?

时间:2018-09-24 14:05:03

标签: opencv image-processing convex-hull convexity-defects

OpenCV函数convexityDefects()中用于计算轮廓的凸度缺陷的算法是什么?

请描述和说明算法的高级操作及其输入和输出。

1 个答案:

答案 0 :(得分:3)

基于documentation,输入是两个坐标列表:

  • contour定义原始轮廓(下图为红色)
  • convexhull定义了与该轮廓相对应的凸包(下图为蓝色)

Example contour and convex hull

algorithm的工作方式如下:

如果轮廓或船体包含的点少于3个,则轮廓始终为凸形,不需要进行更多处理。该算法可确保以相同的方向访问轮廓和船体。

NB: 在进一步的解释中,我假设它们的方向相同,并且忽略了有关将浮点深度表示为整数的详细信息。 / em>

然后对于定义凸包的一个边缘的每对相邻船体点(H[i]H[i+1]),计算轮廓C[n]上每个点到边缘的距离位于H[i]H[i+1]之间(不包括C[n] == H[i+1])。如果距离大于零,则存在缺陷。如果存在缺陷,则记录ii+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)*比例


在上图所示的场景中,在第一次迭代中,边缘由CH[0]定义。检查该边缘的轮廓点是H[1]C[0]C[1](自C[2]起)。

First edge

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]起,最后一个轮廓点可以忽略-那里没有缺陷。