OpenCV Error: Assertion failed (total >= 0 && (depth == 4 || depth == 5)) in pointPolygonTest

参考:

1、OpenCV: Structural Analysis and Shape Descriptors

2、OpenCV: Point Polygon Test

3、pointPolygonTest() throws error for some reason - OpenCV Q&A Forum

网上挺多的示例是从像素图中查找出轮廓使用,我现在是知道多边形的点集要判断某点是否在多边形轮廓内。

要求contour是一个numpy数组或者一个OpenCV标量(即四元素vector Basic Structures — OpenCV 2.4.13.7 documentation

template<typename _Tp> class CV_EXPORTS Scalar_ : public Vec<_Tp, 4>
{
public:
    //! various constructors
    Scalar_();
    Scalar_(_Tp v0, _Tp v1, _Tp v2=0, _Tp v3=0);

>>> cv2.pointPolygonTest(polygon,(0.25,0.25),False)>>> polygon = [(0,0),(1,0),(0,1)]

Traceback (most recent call last):

  File "<stdin>", line 1, in <module>

TypeError: contour is not a numpy array, neither a scalar

改用numpy:

>>> polygon = np.array([(0,0),(1,0),(0,1)],np.int32)
>>> pt = (0.25,0.25)
>>> binside = cv2.pointPolygonTest(polygon,pt,False)
>>> binside
1.0

使用python数据结构如列表构造numpy数组:

>>> import numpy as np
>>> import cv2
>>> polygon = [(0,0),(1,0),(0,1)]
>>> narr = np.array(polygon)
>>> pt = (0.25,0.25)
>>> cv2.pointPolygonTest(narr,pt,False)
1.0
>>> pt = (1,1)
>>> cv2.pointPolygonTest(narr,pt,False)
-1.0
>>> pt = (1,0)
>>> cv2.pointPolygonTest(narr,pt,False)
0.0
>>>

但如果contour的numpy数组或scalar元素的数据类型不是整数是float就会报错:

>>> contour = [(15,-5),(17,-4),(19,-5.9)]
>>> narr = np.array(contour)
>>> pt = (1,2)
>>> cv2.pointPolygonTest(narr,pt,False)
OpenCV Error: Assertion failed (total >= 0 && (depth == 4 || depth == 5)) in pointPolygonTest, file /tmp/binarydeb/ros-kinetic-opencv3-3.3.1/modules/imgproc/src/geometry.cpp, line 103
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
cv2.error: /tmp/binarydeb/ros-kinetic-opencv3-3.3.1/modules/imgproc/src/geometry.cpp:103: error: (-215) total >= 0 && (depth == 4 || depth == 5) in function pointPolygonTest

>>>

换成整数就没问题:

>>> contour = [(15,-5),(17,-4),(19,-6)]
>>> narr = np.array(contour)
>>> pt = (1,2)
>>> cv2.pointPolygonTest(narr,pt,False)	#负整数没关系
-1.0

报错出处opencv3-3.3.1的geometry.cpp可在OpenCV的GitHub找到:

double cv::pointPolygonTest( InputArray _contour, Point2f pt, bool measureDist )
{
    CV_INSTRUMENT_REGION()

    double result = 0;
    Mat contour = _contour.getMat();
    int i, total = contour.checkVector(2), counter = 0;
    int depth = contour.depth();
    CV_Assert( total >= 0 && (depth == CV_32S || depth == CV_32F));

取contour元素深度,也就是数据类型,在Python中上例-6与-5.9分别是int和float,在我64位mac上都是4字节:

>>> sys.getsizeof(-5.9)
24
>>> sys.getsizeof(6)
24

但可能在通过CPython转到底层C++执行时会将-5.9转成8字节的double:

为了尽可能保证精度,我将contuor和pt的数据都乘个1000后取整,这对判断“点在多边形内外”的误差影响我可以接受,当double cv::pointPolygonTest( InputArray _contour, Point2f pt, bool measureDist )的measureDist为True,也就是计算点到多边形距离时将结果再除回1000就可以了,都是线性放大缩小。

20211011更新,构造np数组时指定元素类型为4字节即可

>>> contour = [(15,-5),(17,-4),(19,-5.9)]

>>> narr = np.array(contour,np.float32) # 构造np.array时指定元素类型为np.float32,4字节

>>> pt = (1,2)

>>> cv2.pointPolygonTest(narr,pt,False)

-1.0

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值