OpenCV pointPolygonTest()不工作正常

huangapple go评论48阅读模式
英文:

OpenCV pointPolygonTest() not working correctly

问题

我想将图像分成6个相等的区域(如图所示),然后我想知道一个点属于哪个区域。我正在使用pointPolygonTest()来检查一个点是否在轮廓内部,但对于某些区域来说,它有效,但对于另一些区域来说,却无效。

下面是我的代码。我已经包括了一个测试,在其中它可以正常工作,还有一个测试在其中它不工作,因为它说这个点不属于任何区域,但从图片中可以清楚地看到它是属于的。

输入:

img_path = "../tokyo.jpg"
im = cv2.imread(img_path)
im = cv2.cvtColor(im, cv2.COLOR_BGR2RGB)

xs = [0,im.shape[0]//2,im.shape[0]]
ys = [0,im.shape[1]//3,im.shape[1]//3*2,im.shape[1]]

contours = []

for i in range(len(xs)-1):
for j in range(len(ys)-1):
box = np.array([[xs[i],ys[j]],[xs[i],ys[j+1]],[xs[i+1],ys[j]],[xs[i+1],ys[j+1]]],dtype=np.int32)
contours.append(box)

for c in contours:
im = cv2.rectangle(im,(c[0]),(c[3]), (0, 255, 0), 10) # 绿色
plt.imshow(im)
plt.show()


输出:[![countours and point](https://i.stack.imgur.com/6uPnS.png)](https://i.stack.imgur.com/6uPnS.png)

输入:

for i,c in enumerate(contours):
distance = cv2.pointPolygonTest(c, (400,400), measureDist=False)
if distance >= 0:
print(f"点在轮廓{i+1}内")
else:
print(f"点在轮廓{i+1}外")


输出:

点在轮廓1外
点在轮廓2外
点在轮廓3外
点在轮廓4外
点在轮廓5外
点在轮廓6外

从图片中清楚地可以看出应该显示"点在轮廓5内"。下面是一个可以正常工作的代码,只需稍微调整一下距离(几个像素),所以我不知道为什么会发生这种情况。也许我漏掉了什么。任何帮助将不胜感激。

输入:将点从(400,400)改为(300,400)

for i,c in enumerate(contours):
distance = cv2.pointPolygonTest(c, (300,400), measureDist=False)
...


输出:

点在轮廓1外
点在轮廓2内
点在轮廓3外
点在轮廓4外
点在轮廓5外
点在轮廓6外

更新:我测试了几次,发现当点位于图像的左半部分时,它可以正常工作,但当点位于右半部分时,它就不能工作。对此背后的原因一无所知。
英文:

I want to split an image in 6 equal areas (as seen in the picture) and then I want to know to which area a point belongs to. I'm using pointPolygonTest() to check whether a point is inside a contour or not, the thing is for certain areas it works but for some others it doesn't.

Below I show my code to do so. I have included a test where it works correctly and other where it doesn't because it says the point does not belong to any area, while in the picture it can clearly be seen it does.

Input:

img_path = "../tokyo.jpg"
im = cv2.imread(img_path)
im = cv2.cvtColor(im, cv2.COLOR_BGR2RGB)

xs = [0,im.shape[0]//2,im.shape[0]]
ys = [0,im.shape[1]//3,im.shape[1]//3*2,im.shape[1]]

contours = []

for i in range(len(xs)-1):
    for j in range(len(ys)-1):
        box = np.array([[xs[i],ys[j]],[xs[i],ys[j+1]],[xs[i+1],ys[j]],[xs[i+1],ys[j+1]]],dtype=np.int32)
        contours.append(box)

for c in contours:
    im = cv2.rectangle(im,(c[0]),(c[3]), (0, 255, 0), 10) # green
# im = cv2.circle(im, (400,400), radius=1, color=(255, 0, 0), thickness=10)
plt.imshow(im)
plt.show()

Output:OpenCV pointPolygonTest()不工作正常

Input:

for i,c in enumerate(contours):
    distance = cv2.pointPolygonTest(c, (400,400), measureDist=False)
    if distance >= 0:
        print(f"Point is inside the contour {i+1}")
    else:
        print(f"Point is outside the contour {i+1}")

Output:

Point is outside the contour 1
Point is outside the contour 2
Point is outside the contour 3
Point is outside the contour 4
Point is outside the contour 5
Point is outside the contour 6

From the picture it is clear it should say "Point is inside the contour 5". Below you can find a code where it does work and just by changing the distance a few pixels, so I don't know why does this happen. Maybe I'm missing something. Any help would be appreciated.

Input: changed the point from (400,400) to (300,400)

for i,c in enumerate(contours):
    distance = cv2.pointPolygonTest(c, (300,400), measureDist=False)
    ...

Output:

Point is outside the contour 1
Point is inside the contour 2
Point is outside the contour 3
Point is outside the contour 4
Point is outside the contour 5
Point is outside the contour 6

Update: I just tested a few more times and realized it does work when the point is in the left-half of the image, but when is on the right it doesn't. No idea for the reason behind this.

答案1

得分: 2

这定义了以下顺序的点(假设您已经修复了宽度/高度混淆):

  • 左上角
  • 右上角
  • 左下角
  • 右下角

那不是一个轮廓,而是一个自相交的沙漏。

这些点需要正确排序。只需重新排序最后两个坐标。

注意:不,OpenCV的轮廓没有什么特殊之处。它们只是NumPy数组。它们应该具有形状(N,1,2),但(N,2)也可能起作用。

英文:

Your code:

box = np.array([
    [ xs[i],   ys[j]   ],
    [ xs[i],   ys[j+1] ],
    [ xs[i+1], ys[j]   ],
    [ xs[i+1], ys[j+1] ]
], dtype=np.int32)

This defines the points in the following order (assuming you've fixed the width/height mixup):

  • top left
  • top right
  • bottom left
  • bottom right

That's not a contour, that's a self-intersecting hourglass.

The points need to be ordered correctly. Just reorder the last two coordinates.

Note: no, OpenCV contours are nothing special. they're just numpy arrays. They should have the shape (N, 1, 2) but (N, 2) will probably work too.

答案2

得分: 1

im.shape[0] - 是图像的高度
im.shape[1] - 宽度

xs = [0,im.shape[1]//2,im.shape[1]]
ys = [0,im.shape[0]//3,im.shape[0]//3*2,im.shape[0]]
英文:

im.shape[0] - is height of the image
im.shape[1] - width

xs = [0,im.shape[1]//2,im.shape[1]]
ys = [0,im.shape[0]//3,im.shape[0]//3*2,im.shape[0]]

huangapple
  • 本文由 发表于 2023年5月22日 16:21:43
  • 转载请务必保留本文链接:https://go.coder-hub.com/76304269.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定