OpenCV如何计算凸性缺陷?

muh*_* uk 3 opencv image-processing convex-hull convexity-defects

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

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

Dan*_*šek 5

根据文档,输入是两个坐标列表:

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

示例轮廓和凸包

算法以以下方式工作:

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

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

然后,对于每对相邻的船体的点(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
Run Code Online (Sandbox Code Playgroud)

就矢量而言,可能更容易可视化:

  • 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_rotH_rot,但由于分歧比乘法更昂贵的计算,逆用作优化。在循环结束之前也会对其进行预先计算,C[n]以避免重新计算每次迭代。

| H| = sqrt(dx0 * dx0 + dy0 * dy0)

U_rot = H_rot/ | H| = H_rot*scale

然后,之间的点积CU_rot给出从缺陷点到船体边缘的垂直距离,和abs()用于获取在任何方向的正幅值。

距离= abs(U_rotC)= abs(-dy0 * dx + dx0 * dy)*比例


在上图所示的场景中,在第一次迭代中,边由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]。没有缺陷,因此没有任何记录。

由于C[5] == H[3],最后一个轮廓点可以忽略-那里没有缺陷。

  • 插图不错!作为可视化“distance = abs(-dy0 * dx + dx0 * dy) * scale”计算的附加口头解释:它是通过将向量从“H[i]”投影到每个“C[n]”形成的点积船体段方向上从“H[i]”到“H[i+1]”的单位向量,已旋转 90°(因此“scale”和“dx0”<->“dy0”随着符号变化而交换.) (2认同)