Search code examples
pythonopencvgeometrycontournp

pointPolygonTest is not working correctly for the boundries using opencv?


I am trying the function of the pointPolygontest and I wanted to check the boundries and the points inside and outside.

Form the discretion of the function double pointPolygonTest(InputArray contour, Point2f pt, bool measureDist)

Parameters:

contour – Input contour.

pt – Point tested against the contour.

measureDist – If true, the function estimates the signed distance from the point to the nearest contour edge. Otherwise, the function only checks if the point is inside a contour or not. 

When measureDist=false , the return value is +1, -1, and 0, t returns positive (inside), negative (outside), or zero (on an edge) value, correspondingly.

Now I tested the follwoing code for the edges of my polygon and I got not ecpexted results.

The code is the following:

r = 100
src = np.zeros((4*r,4*r),np.uint8)
rows,cols = src.shape
points = [[0.0*r, 0.0*r], [0.0*r,2.0*r], [2.0*r,2.0*r], [2.0*r,0.0*r] ]
print points
points = np.array(points,np.int0)
cv2.polylines(src,[points],True,255,3)
contours,hierarchy = cv2.findContours(src,cv2.RETR_TREE,cv2.CHAIN_APPROX_SIMPLE)
res = np.zeros(src.shape,np.float32) # array to store distances
drawing = np.zeros((rows,cols,3),np.uint8) # image to draw the distance
cnt = contours[0] # We take only one contour for testing
# Calculate distance from each point

print cv2.pointPolygonTest(cnt,(0.0*r,0.0*r),False)
print cv2.pointPolygonTest(cnt,(0.0*r,2.0*r),False)
print cv2.pointPolygonTest(cnt,(2.0*r,0.0*r),False)
print cv2.pointPolygonTest(cnt,(2.0*r,2.0*r),False)

The Output is

[[0.0, 0.0], [0.0, 200.0], [200.0, 200.0], [200.0, 0.0]]
-1.0
-1.0
-1.0
 1.0

which means that 3 boubdries are outdside and the last one inside but in what I understood is that all of them should be 0.0

So, What is mistake ??


Solution

  • I tired to reproduce. You can check the contour values and also the reason for -1.0 and 1.0.

    [199, 2; 199, 198; 198, 199; 2, 199; 2, 201; 200, 201; 201, 200; 201, 2]
    

    Try

    cv2.fillPoly
    points = [[1.0, 1.0], [1.0,2.0*r], [2.0*r,2.0*r], [2.0*r,1.0] ]
    

    Instead of

    points = [[0.0*r, 0.0*r], [0.0*r,2.0*r], [2.0*r,2.0*r], [2.0*r,0.0*r] ]
    

    The boundaries are usually omitted in pointPolygon (instance 0,0 or 400,400) will not return 0 as expected instead will return -1