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

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

【问题讨论】:

    标签: image opencv image-processing computer-vision detection


    【解决方案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() 在黑框上绘制我的凸包白色来解决这个问题

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

    【讨论】:

      猜你喜欢
      • 2011-02-09
      • 1970-01-01
      • 2014-09-05
      • 2014-03-09
      • 2017-10-09
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多