我有白色背景和简单形状的图像(每个图像都有一个形状)。我想确定某个点 (x,y) 是否在形状内。我怎么能用opencv做到这一点?
3 回答
使用pointPolygonTest
功能。这是教程。
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()
如果你想访问凸包内的所有点,你可以做掩蔽
我首先用 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