直线拟合(Ransac + Opencv)

本文探讨了使用Ransac算法结合OpenCV进行直线拟合的过程,详细解析了一个常见错误“OpenCVError: Assertion failed (npoints2>=0||npoints3>=0) in fitLine”的原因及解决方案,涉及遍历器数据越界的修正。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

直线拟合(Ransac+Opencv)

Ransac原理

Ransac直线拟合原理(待补充)

代码

出现的Bug

OpenCV Error: Assertion failed (npoints2 >= 0 || npoints3 >= 0) in fitLine

原因
代码错误表明问题出现在fitLine(),下面是Opencv提供的源码

void cv::fitLine( InputArray _points, OutputArray _line, int distType,  double param, double reps, double aeps )
{
    CV_INSTRUMENT_REGION();
    Mat points = _points.getMat();

    float linebuf[6]={0.f};
    int npoints2 = points.checkVector(2, -1, false);
    int npoints3 = points.checkVector(3, -1, false);

    CV_Assert( npoints2 >= 0 || npoints3 >= 0 );

    if( points.depth() != CV_32F || !points.isContinuous() )
    {
        Mat temp;
        points.convertTo(temp, CV_32F);
        points = temp;
    }

    if( npoints2 >= 0 )
        fitLine2D( points.ptr<Point2f>(), npoints2, distType,
                   (float)param, (float)reps, (float)aeps, linebuf);
    else
        fitLine3D( points.ptr<Point3f>(), npoints3, distType,
                   (float)param, (float)reps, (float)aeps, linebuf);

    Mat(npoints2 >= 0 ? 4 : 6, 1, CV_32F, linebuf).copyTo(_line);
    
}

可以发现错误提示来自CV_Assert(npoints2 >= 0 || npoints3 >= 0)

研究函数 checkVector() 的定义

int cv::Mat::checkVector
(   int elemChannels, 
	int depth = -1, 
	bool requireContinuous = true 
)const

调用checkVector() 的矩阵,我的理解是用checkVector() 来检查矩阵的通道数和连续性,无误时可以返回矩阵的维数,二维Mat返回2,三维Mat返回3,否则返回-1

再看一下矩阵points是由以下代码生成的

Mat points = _points.getMat();

由此可以判断出我代码中出现问题的部分是 进入fitLIine()时_points传参的时候出现了问题
进而检查代码(如下)

detectangle_step = 4;
detectangle_width = 30;
for (int i = 0 ; i < 1080/detectangle_step; i++){

   	std::vector<Point2d>::const_iterator first1 = ptSet_original.begin() + i*detectangle_step;
    std::vector<Point2d>::const_iterator last1  = ptSet_original.begin() + i*detectangle_step + detectangle_width;
    std::vector<Point2d> ptSet(first1, last1);

    fitLineRANSAC(ptSet, A, B, C, inliers);
    ...(省略)
}

产生问题的是遍历器数据出现了越界情况
在代码中,ptSet一共只有1080个数据,而最开始的代码版本由于编写的问题,i最大可能出现超过1080的情况
正是由于这个原因,导致代码在运行初始和运行阶段,必然由于遍历器超过数据实际长度引发assert

解决方案
更改代码为

detectangle_step = 4;
detectangle_width = 30;
for (int i = 0 ; i < (1080 - detectangle_width)/detectangle_step; i++){

   	std::vector<Point2d>::const_iterator first1 = ptSet_original.begin() + i*detectangle_step;
    std::vector<Point2d>::const_iterator last1  = ptSet_original.begin() + i*detectangle_step + detectangle_width;
    std::vector<Point2d> ptSet(first1, last1);

    fitLineRANSAC(ptSet, A, B, C, inliers);
    ...(省略)
}

成功!不再报错了

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值