These days in debugging a OPENCV demo program, always crash, diagnostic information for
| 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>::d epth) & ((1 << 3)-1)) & (+) = = ElemSize1 ()) in Cv::mat::at, file u:\opencv\opencv-2.4.9\sources\modules\core\include\opencv2/core/mat.hpp, line 545 |
Call Stack is
opencv_core249d.dll!cv::error (const cv::exception & exc={...}) Line 546 C + + OPENCV_CALIB3D249D.DLL!CV::MAT::AT<CV::P oint3_<float> > (int i0=0, int i1=1) line 543 + 0xf6 bytes c++< /c1> OPENCV_CALIB3D249D.DLL!EPNP::INIT_POINTS<CV::P OINT3_<FLOAT>,CV::P oint_<float> > (const CV:: Mat & opoints={...}, const Cv::mat & ipoints={...}) Line + 0xe bytes C + + Opencv_calib3d249d.dll!epnp::epnp (const Cv::mat & cameramatrix={...}, const Cv::mat & opoints={...}, const Cv::mat & ipoints={...}) Line 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) Lin E + 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 + +
|
Searched the internet and found no valuable clues. So I decided to take some time to debug and see what the problem was.
From Cv::error to the upper layer, enter the Mat::at function
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>::d epth) = = ElemSize1 ()); return ((const _tp*) (data + step.p[0]*i0)) [I1]; } |
Look at the contents of 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 is a 7x1 two-dimensional matrix with an element type of point3f and a call to an at function to take the element with coordinates (0,1). This is a problem, 7x1 's two-dimensional matrix does not exist (0,1) This coordinate ah, the appearance of assertion will be this reason.
A few more careful examination of Cv_dbgassert 's judgment conditions, found that the problem is here: (unsigned) (i1*datatype<_tp>::channels) < (unsigned) ( Size.p[1]*channels ())
This judgment means: column coordinates * Number of channels of the element < number of matrix columns * Number of matrix channels; because the number of element channels (Datatype<point3f>::channels) and the number of matrix channels (channels ()) are 3 A second simplification is: column coordinates < number of matrix columns.
This makes it clear that this is a boundary detection for column coordinates, and a assertion error occurs because column coordinate 1 is out of bounds.
Then go up into the upper-level function 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; } } |
Judging from this code, it seems to be to ignore the row/column structure of the matrix, forcing the matrix to be accessed as a one-dimensional array, but it throws a diagnostic error in the at function due to boundary check recognition.
To confirm this, I looked at the epnp::init_points code in Opencv-3.0-beta and found that it had been changed to:
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; } }
|
I can't believe there are such obvious bugs in the official release release. If not the bug, then why the demo from 2.4.9 to 3.0.
opencv-2.4.9 's bug?