标签:style io ar color os sp for strong on
这几天在调试一个opencv的demo程序,总是crash,诊断信息为
OpenCV Error: Assertion failed (dims <= 2 && data && (unsigned)i0 < (unsigned)size.p[0] && (unsigned)(i1*DataType<_Tp>::channels) < (unsigned)(size.p[1]*channels()) && ((((sizeof(size_t)<<28)|0x8442211) >> ((DataType<_Tp>::depth) & ((1 << 3) - 1))*4) & 15) == elemSize1()) in cv::Mat::at, file U:\OpenCv\opencv-2.4.9\sources\modules\core\include\opencv2/core/mat.hpp, line 545 |
call stack为
opencv_core249d.dll!cv::error(const cv::Exception & exc={...}) Line 546 C++ opencv_calib3d249d.dll!cv::Mat::at<cv::Point3_<float> >(int i0=0, int i1=1) Line 543 + 0xf6 bytes C++ opencv_calib3d249d.dll!epnp::init_points<cv::Point3_<float>,cv::Point_<float> >(const cv::Mat & opoints={...}, const cv::Mat & ipoints={...}) Line 29 + 0xe bytes C++ opencv_calib3d249d.dll!epnp::epnp(const cv::Mat & cameraMatrix={...}, const cv::Mat & opoints={...}, const cv::Mat & ipoints={...}) Line 22 C++ opencv_calib3d249d.dll!cv::solvePnP(const cv::_InputArray & _opoints={...}, const cv::_InputArray & _ipoints={...}, const cv::_InputArray & _cameraMatrix={...}, const cv::_InputArray & _distCoeffs={...}, const cv::_OutputArray & _rvec={...}, const cv::_OutputArray & _tvec={...}, bool useExtrinsicGuess=false, int flags=1) Line 64 + 0x1d bytes C++ SHPE.exe!loadWithPoints(cv::Mat & ip={...}, cv::Mat & img={...}) Line 326 + 0xc4 bytes C++ SHPE.exe!loadNext() Line 311 + 0x13 bytes C++ SHPE.exe!main(int argc=1, char * * argv=0x0261e310) Line 408 C++ |
在网上搜了一下,也没找到什么有价值的线索。于是决定自己花点功夫调试一下,看看究竟是什么问题。
从cv::error往上一层,进入Mat::at函数
template<typename _Tp> inline const _Tp& Mat::at(int i0, int i1) const { CV_DbgAssert( dims <= 2 && data && (unsigned)i0 < (unsigned)size.p[0] && (unsigned)(i1*DataType<_Tp>::channels) < (unsigned)(size.p[1]*channels()) && CV_ELEM_SIZE1(DataType<_Tp>::depth) == elemSize1()); return ((const _Tp*)(data + step.p[0]*i0))[i1]; } |
查看一下this的内容
this 0x003be898 {flags=1124024341 dims=2 rows=7 ...} const cv::Mat * const flags 1124024341 int dims 2 int rows 7 int cols 1 int |
this是一个7x1的二维矩阵,元素类型为Point3f; 调用了at函数取坐标为(0,1)的元素。这就有问题了,7x1的二维矩阵不存在(0,1)这个坐标呀,出现assertion会不会是这个原因呢。
再仔细检测 CV_DbgAssert的几个判断条件,发现问题出在这里: (unsigned)(i1*DataType<_Tp>::channels) < (unsigned)(size.p[1]*channels())
这个判断的意思是:列坐标 * 元素的通道数 < 矩阵列数 * 矩阵通道数;由于元素通道数(DataType<Point3f>::channels)和矩阵通道数(channels())都为3;再化简一下就是:列坐标 < 矩阵列数。
这样一来就明白了这个判断是对列坐标做边界检测;由于列坐标1超出了边界,所以出现了assertion错误。
再往上进入上一级函数epnp::init_points:
template <typename OpointType, typename IpointType> void init_points(const cv::Mat& opoints, const cv::Mat& ipoints) { for(int i = 0; i < number_of_correspondences; i++) { pws[3 * i ] = opoints.at<OpointType>(0,i).x; pws[3 * i + 1] = opoints.at<OpointType>(0,i).y; pws[3 * i + 2] = opoints.at<OpointType>(0,i).z; us[2 * i ] = ipoints.at<IpointType>(0,i).x*fu + uc; us[2 * i + 1] = ipoints.at<IpointType>(0,i).y*fv + vc; } } |
从这段代码来看,似乎是要无视矩阵的行/列结构,强制将矩阵当成一个一维数组来访问;却在at函数中由于边界检查识别而抛出了诊断错误。
为了印证这一点,我又查看了opencv-3.0-beta中epnp::init_points的代码,发现已经被改成:
template <typename OpointType, typename IpointType> void init_points(const cv::Mat& opoints, const cv::Mat& ipoints) { for(int i = 0; i < number_of_correspondences; i++) { pws[3 * i ] = opoints.at<OpointType>(i).x; pws[3 * i + 1] = opoints.at<OpointType>(i).y; pws[3 * i + 2] = opoints.at<OpointType>(i).z; us[2 * i ] = ipoints.at<IpointType>(i).x*fu + uc; us[2 * i + 1] = ipoints.at<IpointType>(i).y*fv + vc; } } |
真是不敢相信在正式的release版本中会存在这么明显的bug。如果不是bug,那为什么demo从2.4.9换到3.0就好了。
标签:style io ar color os sp for strong on
原文地址:http://www.cnblogs.com/panruochen/p/4141442.html