61

I'm trying to draw an arbitrary quadrilateral over an image using the polylines function in opencv. When I do I get the following error

OpenCV Error: Assertion failed (p.checkVector(2, CV_32S) >= 0) in polylines, file /tmp/buildd/ros-fuerte-opencv2-2.4.2-1precise-20130312-1306/modules/core/src/d rawing.cpp, line 2065

I call the function as like so,

cv2.polylines(img, points, 1, (255,255,255)) 

Where points is as numpy array as shown below (The image size is 1280x960):

[[910 641] [206 632] [696 488] [458 485]] 

and img is just a normal image that I'm able to imshow. Currently I'm just drawing lines between these points myself, but I'm looking for a more elegant solution.

How should I correct this error?

1
  • cv2.polylines(img, np.reshape(p, (1, *p), 1, (255,255,255)) Commented Dec 13, 2020 at 8:11

9 Answers 9

91

The problem in my case was that numpy.array created int64-bit numbers by default. So I had to explicitly convert it to int32:

points = np.array([[910, 641], [206, 632], [696, 488], [458, 485]]) # points.dtype => 'int64' cv2.polylines(img, np.int32([points]), 1, (255,255,255)) 

(Looks like a bug in cv2 python binding, it should've verified dtype)

Sign up to request clarification or add additional context in comments.

3 Comments

You can also use np.array(..., dtype=np.int32).
The reason this works in not because of the type conversion, but because you are converting the points into an array of points. The second c++ arg is input array of array
Actually I spoke too soon. The type matters too. There is a check for checkVector(2, CV_32S) within polylines which fail if you don't pass in an 32 bit int.
50

This function is not enough well documented and the error are also not very useful. In any case, cv2.polylines expects a list of points, just change your line to this:

import cv2 import numpy as np img = np.zeros((768, 1024, 3), dtype='uint8') points = np.array([[910, 641], [206, 632], [696, 488], [458, 485]]) cv2.polylines(img, [points], 1, (255,255,255)) winname = 'example' cv2.namedWindow(winname) cv2.imshow(winname, img) cv2.waitKey() cv2.destroyWindow(winname) 

The example above will print the following image (rescaled):

enter image description here

7 Comments

I tried it but I still get the same error. This is how the argument for points looks like now: [array([[902, 636], [222, 625], [458, 485], [696, 488]])]
I have updated the code, and as you can see the code works perfectly good.
The example program given by you gives me the same error. OpenCV Error: Assertion failed (p.checkVector(2, CV_32S) >= 0) in polylines, file /tmp/buildd/ros-fuerte-opencv2-2.4.2-1precise-20130312-1306/modules/core/src/drawing.cpp, line 2065 Maybe it's an issue with my version!!
To make it work I had to convert [points] to int32: cv2.polylines(img, np.int32([points]), 1, (255,255,255))
[points] solved it for me as well, and my points were already in int32.
|
14

the error says your array should be of dimension 2. So reshape the array as follows:

points = points.reshape(-1,1,2) 

Then it works fine.

Also, answer provided by jabaldonedo also works fine for me.

Comments

3

Replace cv2.fillPoly( im, np.int32(points)) with cv2.fillPoly( im, np.int32([points])). It will work.

Comments

1
pts = np.array([[40,300],[54,378],[60,420],[30,333]],np.int32) pts = pts.reshape((-1,1,2)) img = cv2.polylines(img,pts,True,(125,215,145),1) 

The official documentation to provide explanation,need reshape

1 Comment

You actually only need to pass pts as a list of pts. The pts are one figure. You can pass a list of figures. So use img = cv2.polylines(img, [pts],True,(125,215,145),1) No need to reshape
1

I also faced the same problem The solution is to make a array of 1 row, 2 columns and - 1 depth, - 1 means unknown dimensions so numpy will assign convenient depth to the array. If you make array of more than 1 row and 2 columns it will show error.

Also this error can come when the array you created is not of type int32

Vertices = np.array([[36,86] ,[73,73], [87,87]], dtype=np.int32) 

Comments

1
import cv2 import numpy as np sz, sh, of = 1000, 500, 100 # Create an Empty image with white background im = 255 * np.ones(shape=[sz, sz, 3], dtype=np.uint8) # Draw shapes im = cv2.polylines( img=im, pts=[np.int32([ [of, of], [sh, of + of], [sz - of, of], [sz-of-of,sh], [sz-of,sz-of], [sh,sz-of-of], [of,sz-of], [of+of,sh]])], isClosed=True, color=(128, 0, 200), thickness=30, lineType=cv2.LINE_AA, # Anti-Aliased ) cv2.imwrite("polylines.jpg", im) 

enter image description here

Comments

1

Convert it into an array of points instead of passing as pts as shown below:

The right way to pass points:

cv2.polylines(img, [points], 1, (255,255,255)) 

The wrong way to pass points:

cv2.polylines(img, points, 1, (255,255,255)) 

Comments

0

vertices = np.array([[pts]], dtype=np.int32) works for me

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.