58

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?

Ashok
  • 1,079
  • 3
  • 10
  • 17

9 Answers9

86

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)

Vanuan
  • 31,770
  • 10
  • 98
  • 102
  • 16
    You can also use `np.array(..., dtype=np.int32)`. – Nils Werner Aug 04 '14 at 11:29
  • 7
    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 – nnrales Aug 31 '17 at 15:27
  • 2
    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. – nnrales Aug 31 '17 at 16:23
48

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

jabaldonedo
  • 25,822
  • 8
  • 77
  • 77
  • 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]])]` – Ashok Jun 21 '13 at 20:06
  • I have updated the code, and as you can see the code works perfectly good. – jabaldonedo Jun 21 '13 at 20:31
  • 2
    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!! – Ashok Jun 21 '13 at 21:00
  • 1
    To make it work I had to convert `[points]` to int32: `cv2.polylines(img, np.int32([points]), 1, (255,255,255))` – Vanuan Sep 15 '13 at 20:20
  • 5
    `[points]` solved it for me as well, and my `points` were already in `int32`. – letmaik Jan 13 '14 at 08:33
  • the trick is to convert points to int32 and add `[ ]` around the points and . it works for me. – Franva May 02 '21 at 00:24
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.

Abid Rahman K
  • 51,886
  • 31
  • 146
  • 157
3

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

Suraj Rao
  • 29,388
  • 11
  • 94
  • 103
Ranjeet Singh
  • 159
  • 10
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)
aminography
  • 21,986
  • 13
  • 70
  • 74
Resfe
  • 51
  • 4
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

Shamshirsaz.Navid
  • 2,224
  • 3
  • 22
  • 36
0
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

xm L
  • 11
  • 3
  • 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 – Ray Lutz Mar 01 '23 at 19:26
0

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

0

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))
Achyut Sarma
  • 119
  • 7