[edited] It appears there is a new bug in opencv that introduces an issue causing fillPoly
's boundaries to exceed polylines
's.
Here is humble code to draw a red filled polygon with a blue outline.
import cv2
import numpy as np
def draw_polygon(points, resolution=50):
# create a blank black canvas
img = np.zeros((resolution, resolution, 3), dtype=np.uint8)
pts = np.array(points, np.int32)
pts = pts.reshape((-1, 1, 2))
# draw a filled polygon in blue
cv2.fillPoly(img, [pts], (0, 0, 255))
# draw an outline in red
cv2.polylines(img, [pts], True, (255, 0, 0), 1)
# show the image
cv2.imshow("Polygon", img)
cv2.waitKey(0)
cv2.destroyAllWindows()
# why is the infill outside the line?
if __name__ == "__main__":
# 4 vertices of the quad (clockwise)
quad = np.array([[[44, 27],
[7, 37],
[7, 19],
[38, 19]]])
draw_polygon(quad)
QUESTION
The polygon's infill appears to bleed outside of the outline (two highlighted pixels). I'm looking for a temporary solution until this bug is addressed so the infill stays completely inside the outline.
Solution has to work with concave polygons.
Where there's a will there's a way. fillPoly
appears to be able to draw as a line when given only two vertices. And that line matches the edges of the previously drawn polygon. \o/
I modified my code to draw the edges as a single fillPoly
call and it seems to work decently.
I would still prefer if fillPoly
and polyLines
would match, but for now I am unblocked.
import cv2
import numpy as np
def draw_polygon(points, resolution=50):
# create a blank black canvas
img = np.zeros((resolution, resolution, 3), dtype=np.uint8)
poly_pts = np.array(points, np.int32)
edge_pts = np.vstack([poly_pts, poly_pts[0]])
# draw a filled polygon in blue
cv2.fillPoly(img, [poly_pts], (0, 0, 255))
# draw the outlines as individual edges,
# drawn in a single fillPoly call, in red
e0 = edge_pts[:-1]
e1 = edge_pts[1:]
edge_polygons = np.hstack((e0[:,None], e1[:,None]))
cv2.fillPoly(img, edge_polygons, (255, 0, 0))
# show the image
cv2.imshow("Polygon", img)
cv2.waitKey(0)
cv2.destroyAllWindows()
# better outline
if __name__ == "__main__":
# 4 vertices of the quad (clockwise)
quad = np.array([[44, 27],
[7, 37],
[7, 19],
[38, 19]])
draw_polygon(quad)