如何在OpenCV中检测一个轮廓是否嵌套/包含其他轮廓

12

我有两个轮廓,想要检查它们之间的关系(是否嵌套)。通常情况下,我会使用findContours函数,并设置CV_RETR_TREE检索模式。然而,我从不同的源获取了这些轮廓(使用MSER方法)。实际上,我不仅有轮廓,还有区域掩码(如果有帮助的话)。例如,假设我想分割字母'O',那么我将具有以下掩码或轮廓:

1)

0 0 0 0 0 0
0 1 1 1 1 0
0 1 0 0 1 0
0 1 0 0 1 0
0 1 1 1 1 0
0 0 0 0 0 0 

2)

0 0 0 0 0 0
0 0 0 0 0 0
0 0 1 1 0 0
0 0 1 1 0 0
0 0 0 0 0 0
0 0 0 0 0 0 

如何轻松检查第二个轮廓是否在第一个轮廓内?我考虑过检查边界框之间的关系,但这并不能涵盖所有可能的情况。

2个回答

12
使用 cv::pointPolygonTest(InputArray contour, Point2f pt, bool measureDist) 函数可以判断轮廓中的点是否在另一个图形内部。
需要检查边界情况(选择的第一个点是两个多边形共有的点等)。
if(pointPolygonTest(contour, pointFromOtherContour, false) > 0)
{
    // it is inside
}
该函数确定给定点是否在轮廓内部、外部或在边缘上(或与顶点重合),相应返回正数(在内部)、负数(在外部)或零(在边缘上)。当measureDist=false时,返回值分别为+1、-1和0。否则,返回值是点到最近轮廓边缘的有符号距离。

1

如果您知道轮廓是封闭的(在4连通意义下),那么您可能可以使用射线无限测试,这种方法更常用于测试点是否在封闭多边形内。 (还假设轮廓不会交叉,这可能是不可能的。)

取候选轮廓上的任意一点,并从任何方向(为了实现方便,选择一个轴对齐的方向)开始朝“无限”方向前进:如果您一直走到图像的边缘并且跨越外部轮廓奇数次,则您开始的轮廓在该轮廓内部。

“穿过”外轮廓实际上有点棘手,例如:

  . 1 1 1 1 1 1 1
  . 1 . . X X X 1
  . 1 . . X . X 1
<-.-1-1-.-X X X 1 : here a naiive implementation counts two crossings
  . . 1 1 1 1 1 1

因此,要测试一条射线在某个点是否“穿过”轮廓,您确实需要考虑3x3相邻点。我认为您最终会得到一组类似于这样的情况:

  . . .
<-1-1 1 // not crossing
  . . .

  1 . 1
<-1-1 1 // not crossing
  . . .

  . . 1
<-1-1 1 // crossing
  . . .

  1 . .
<-1-1 1 // crossing
  . . .

我不确定是否可能基于3x3邻域构建一致的测试来检测4连通轮廓的交叉,但很可能是可以的。

当然,这一切都依赖于外部轮廓是封闭的。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接