Python中的Opencv polylines函数抛出异常

59
我试图在一张图片上使用OpenCV的polylines函数绘制任意四边形,但是当我尝试这样做时,会出现以下错误:

OpenCV错误:在polylines函数中断言失败(p.checkVector(2,CV_32S)> = 0),文件/tmp/buildd/ros-fuerte-opencv2-2.4.2-1precise-20130312-1306/modules/core/src/drawing.cpp,行2065

我调用函数的方式如下:
cv2.polylines(img, points, 1, (255,255,255))

points是一个numpy数组,如下所示(图像大小为1280x960):

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

同时,img只是一张我能够使用imshow函数显示的普通图片。目前,我正在自己在这些点之间绘制线条,但我正在寻找更优雅的解决方案。

我应该如何纠正这个错误?


cv2.polylines(img, np.reshape(p, (1, *p)), 1, (255,255,255)) - Epsi95
9个回答

87

在我的情况下问题是numpy.array默认创建了int64位数的数字。所以我必须显式地将它转换为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))

看起来是cv2 Python绑定中的一个错误,它应该验证dtype


16
你也可以使用np.array(..., dtype=np.int32) - Nils Werner
8
这个方法之所以有效,并不是因为类型转换,而是因为你将点转换成了一个点数组。C++的第二个参数是输入的二维数组。 - nnrales
2
我说得太早了。类型也很重要。Polyline 中有一个 checkVector(2, CV_32S) 的检查,如果您不传递 32 位整数,则会失败。 - nnrales

48

这个函数的文档描述不够详细,错误信息也不是很有用。无论如何,cv2.polylines期望接受一个点列表,只需要将你的代码修改为:

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)

以上示例将打印以下图像(重新调整大小):

在此输入图片描述


我尝试过了,但仍然出现相同的错误。现在点参数看起来是这样的: [array([[902, 636], [222, 625], [458, 485], [696, 488]])] - Ashok
2
你给我的示例程序也出现了同样的错误。OpenCV错误:在polylines文件/tmp/buildd/ros-fuerte-opencv2-2.4.2-1precise-20130312-1306/modules/core/src/drawing.cpp的第2065行中,断言失败(p.checkVector(2, CV_32S) >= 0)也许这是由于我的版本问题! - Ashok
1
为了使其正常工作,我必须将[points]转换为int32:cv2.polylines(img, np.int32([points]), 1, (255,255,255)) - Vanuan
5
“[points]” 这个方法对我也起了作用,而且我的“points”已经是“int32”类型了。 - letmaik
诀窍是将点转换为int32并在点周围添加 [ ]。这对我很有效。 - Franva
显示剩余2条评论

14

错误提示表示您的数组应为二维。因此,请按以下方式重新调整数组的形状:

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

那么它就可以正常工作。

同时,jabaldonedo提供的答案对我也有效。


3

cv2.fillPoly( im, np.int32(points))替换为cv2.fillPoly( im, np.int32([points]))。这样会有效果。


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


1
我也遇到了同样的问题。解决方法是创建一个行为1,列为2,深度为-1的数组,-1表示未知尺寸,因此numpy会为数组分配方便的深度。如果你创建的数组超过1行2列,它会显示错误。
此外,当你创建的数组不是int32类型时,也会出现这个错误。
Vertices = np.array([[36,86] ,[73,73], [87,87]], dtype=np.int32)

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)

官方文档需要重新整理以提供解释。


实际上,您只需要将pts作为一个pts列表传递即可。pts是一个数字。您可以传递数字列表。因此,请使用img = cv2.polylines(img, [pts],True,(125,215,145),1)无需重新整形。 - Ray Lutz

0

对我来说,vertices = np.array([[pts]], dtype=np.int32)有效。


0
将其转换为点数组而不是像下面显示的那样传递pts:
传递点的正确方法:
cv2.polylines(img, [points], 1, (255,255,255))

传递点的错误方式:

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

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接