使用opencv确定一个点是在形状内部还是外部

Posted

技术标签:

【中文标题】使用opencv确定一个点是在形状内部还是外部【英文标题】:Determine if a point is inside or outside of a shape with opencv 【发布时间】:2012-11-26 23:44:17 【问题描述】:

我有白色背景和简单形状的图像(每张图像都有一个形状)。我想确定某个点 (x,y) 是否在形状内。如何使用 opencv 做到这一点?

【问题讨论】:

【参考方案1】:

使用pointPolygonTest 函数。 Here's教程。

【讨论】:

这个功能有问题。我将其设置为在轮廓内绘制像素。有趣的是它正在旋转形状并确定它是否在里面。你能帮我解决这个问题吗? 抱歉,我对行和列感到困惑,但由于形状无法判断它是 90 度旋转。解决了【参考方案2】:

要确定一个点是在形状的内部、外部还是边缘,您可以使用cv2.pointPolygonTest() 检查该点是否在轮廓内。该函数返回+1-10,分别指示一个点是在轮廓内部、外部还是在轮廓上。假设我们已经有了形状的轮廓,我们可以简单地将轮廓和(x,y) 点传递给函数。

result = cv2.pointPolygonTest(contour, (x,y), False) 

在函数中,第三个参数是measureDist。如果是True,它会找到图像中的点与轮廓之间的最短距离。如果False,它会查找该点是在轮廓内部、外部还是在轮廓上。由于我们不想找到距离,我们将measureDist 参数设置为False

这是一个找到正方形轮廓然后检查点是否在轮廓内的示例


测试图片

找到轮廓和检查点后的图像

结果

点1:-1.0

point2: 1.0

point3: 0.0

因此point1在外面,point2在里面,point3在轮廓上

import cv2

image = cv2.imread('1.png')
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
canny = cv2.Canny(gray, 120, 255, 1)
cnts = cv2.findContours(canny, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
cnts = cnts[0] if len(cnts) == 2 else cnts[1]

point1 = (25, 50)
point2 = (200, 250)
point3 = (200, 350)

# Perform check if point is inside contour/shape
for c in cnts:
    cv2.drawContours(image, [c], -1, (36, 255, 12), 2)
    result1 = cv2.pointPolygonTest(c, point1, False)
    result2 = cv2.pointPolygonTest(c, point2, False)
    result3 = cv2.pointPolygonTest(c, point3, False)

# Draw points
cv2.circle(image, point1, 8, (100, 100, 255), -1)
cv2.putText(image, 'point1', (point1[0] -10, point1[1] -20), cv2.FONT_HERSHEY_SIMPLEX, 1.0, (0, 0, 0), lineType=cv2.LINE_AA)
cv2.circle(image, point2, 8, (200, 100, 55), -1)
cv2.putText(image, 'point2', (point2[0] -10, point2[1] -20), cv2.FONT_HERSHEY_SIMPLEX, 1.0, (0, 0, 0), lineType=cv2.LINE_AA)
cv2.circle(image, point3, 8, (150, 50, 155), -1)
cv2.putText(image, 'point3', (point3[0] -10, point3[1] -20), cv2.FONT_HERSHEY_SIMPLEX, 1.0, (0, 0, 0), lineType=cv2.LINE_AA)

print('point1:', result1)
print('point2:', result2)
print('point3:', result3)
cv2.imshow('image', image)
cv2.waitKey()

【讨论】:

通过 Google 找到答案总是很有趣。【参考方案3】:

如果你想访问凸包内的所有点,你可以做遮罩

我首先用 cv2.fillPoly() 在黑框上绘制我的凸包白色来解决这个问题

    首先创建符合框架形状的黑色框架 black_frame = np.zeros_like(your_frame).astype(np.uint8) 用白色绘制凸包 cv2.fillPoly(black_frame , [hull], (255, 255, 255)) 使用 numpy 布尔索引创建一个掩码,它会生成一个带有 True/False 值的掩码,它将是 True 是像素值是白色的 mask = black_frame == 255 您可以通过获取框架和蒙版之间的乘积来访问像素值,如果为 False,则值将 targetROI = your_frame * mask 使用蒙版访问您的像素。
black_frame = np.zeros_like(your_frame).astype(np.uint8)
cv2.fillPoly(black_frame , [hull], (255, 255, 255))
mask = black_frame == 255
targetROI = your_frame * mask

【讨论】:

以上是关于使用opencv确定一个点是在形状内部还是外部的主要内容,如果未能解决你的问题,请参考以下文章

OpenCV:将不规则形状轮廓的内部设置为颜色

如何在运行时确定应用程序是为内部测试人员还是外部测试人员分发?

检测点击是在自定义 calloutView 内部还是外部

找到非常规二维形状的最长完全内部线的算法?

opencv 如何检测特定形状的物体

telnet不是内部或外部命令怎么办