Home > Blockchain >  How to use cv2.fillpoly function properly
How to use cv2.fillpoly function properly

Time:09-11

I am trying to use the fillpoly function to fill two polygons at once (with a triangle and a trapezium). Please find the below code.

# Import necessary libraries
import cv2
import numpy as np

# Read an image
img = np.zeros((500,500))

# Define an array of endpoints of triangle
points = np.array([[[160, 130], [350, 130], [250, 300]],[[160, 30], [50, 30], [80, 130],[100, 130]]],dtype=object)

# Use fillPoly() function and give input as
# image, end points,color of polygon
# Here color of polygon will blue
for i in range(len(points)):
    cv2.fillPoly(img, pts=[points[i]], color=(255, 0, 0))
#cv2.fillPoly(img, pts=[points[1]], color=(255, 0, 0))


# Displaying the image
cv2.imshow("Triangle", img)

# wait for the user to press any key to
# exit window
cv2.waitKey(0) 

# Closing all open windows
cv2.destroyAllWindows()

However, the output gives me an error. Please find it below.

/var/folders/hh/phtw2ldx7gj88krjgwdbz9680000gn/T/ipykernel_1755/1373141779.py:9: VisibleDeprecationWarning: Creating an ndarray from ragged nested sequences (which is a list-or-tuple of lists-or-tuples-or ndarrays with different lengths or shapes) is deprecated. If you meant to do this, you must specify 'dtype=object' when creating the ndarray.
  points = np.array([[[160, 130], [350, 130], [250, 300]],[[160, 30], [50, 30], [80, 130],[100, 130]]])
---------------------------------------------------------------------------
error                                     Traceback (most recent call last)
Input In [35], in <cell line: 14>()
     11 # Use fillPoly() function and give input as
     12 # image, end points,color of polygon
     13 # Here color of polygon will blue
     14 for i in range(len(points)):
---> 15     cv2.fillPoly(img, pts=[points[i]], color=(255, 0, 0))
     16 #cv2.fillPoly(img, pts=[points[1]], color=(255, 0, 0))
     17 
     18 
     19 # Displaying the image
     20 cv2.imshow("Triangle", img)

error: OpenCV(4.6.0) :-1: error: (-5:Bad argument) in function 'fillPoly'
> Overload resolution failed:
>  - Can't parse 'pts'. Sequence item with index 0 has a wrong type
>  - Can't parse 'pts'. Sequence item with index 0 has a wrong type

It gives an error due to the different number in coordinates of the polygones (3 and 4 respectively).

Would anyone be able to help me in this regards please.

Thanks & Best Regards

Schroter Michael

CodePudding user response:

  1. Your image needs to have 3 channels (np.zeros((500, 500, 3))) instead of 1.
  2. Your coordinates need to be np.int32.
import cv2
import numpy as np

img = np.zeros((500, 500, 3))

# Define an array of points.
points = [
    [[160, 130], [350, 130], [250, 300]],
    [[160, 30], [50, 30], [80, 130], [100, 130]],
]

for poly in points:
    cv2.fillPoly(img, np.array([poly], dtype=np.int32), (255, 0, 0))

# Displaying the image
cv2.imshow("Triangle", img)

# wait for the user to press any key to
# exit window
cv2.waitKey(0)

# Closing all open windows
cv2.destroyAllWindows()

CodePudding user response:

You should write your code like so:

polygons = [
    [[160, 130], [350, 130], [250, 300]], # first polygon, 3 points
    [[160, 30], [50, 30], [80, 130], [100, 130]] # second polygon, 4 points
]

cv2.fillPoly(img, pts=[np.int32(poly) for poly in polygons], color=(255, 0, 0))

Or, if more convenient, keep each polygon's points as a numpy array in the first place.

This API takes a list of polygons and will draw all the given polygons at once. You only need a single call. It does require each polygon to be a numpy array, which gets translated into a cv::Mat. The C signature is something like std::vector<cv::Mat>

pts Array of polygons where each polygon is represented as an array of points.

You should never "just" use dtype=object because that indicates some serious problems that can and should be solved properly in the majority of cases. In this case, you probably tried to shut numpy up because it complained about Creating an ndarray from ragged nested sequences. Numpy is not intended for "ragged arrays", where different subarrays have different lengths (you have a 3-element list and a 4-element list in your list). You can't solve that by passing dtype=object. That'll just put Python lists, shallowly, into a numpy array. As soon as you index the first dimension, all numpy is gone and you're left with the plain python objects, lists here.


Your image does not need to have 3 channels ((H,W,C) with C=3, instead of (H,W)). It's perfectly okay to have a grayscale image, but then you can't put colors into it. The fillPoly call would then require color=255 (scalar value, not a tuple).

  • Related