24

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

4

3 回答 3

26

使用pointPolygonTest功能。这是教程。

于 2012-12-09T09:17:28.613 回答
16

To determine if a point is inside, outside, or on the edge of a shape you can check if the point is within a contour using cv2.pointPolygonTest(). The function returns +1, -1, or 0 to indicate if a point is inside, outside, or on the contour, respectively. Assuming we already have the contour of the shape, we can simply pass the contour and the (x,y) point to the function.

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

In the function, the third argument is measureDist. If it is True, it finds the shortest distance between a point in the image and a contour. If False, it finds whether the point is inside, outside, or on the contour. Since we don't want to find the distance, we set the measureDist argument to False

Here's an example that finds the square contour then checks if the points are within the contour


Test image

Image after finding contour and checking points

Results

point1: -1.0

point2: 1.0

point3: 0.0

Therefore point1 is outside, point2 is inside, and point3 is on the contour

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()
于 2019-10-04T01:42:57.793 回答
0

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

我首先用 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
于 2020-10-18T15:58:08.237 回答