简体   繁体   中英

Why does assertion fail here

Why does the assertion fail here when i create a CvMat * ? It does not happen with an image i load in cv::Mat using a pointer.

    struct RGB { unsigned char b, g, r; };
    cv::Point p;
    RGB *data;
    CvMat* mat = cvCreateMat(300,300,CV_32FC1);
    for( row = 0; row < mat->rows; ++row) 
    {
            for ( col = 0; col < mat->cols; ++col) 
            {
                 p.x=row,p.y=col;
        ERROR ----->>>   assert((mat->step/mat->cols) == sizeof(RGB));
                 data = (RGB*)&mat->data;
                 data += p.y * mat->cols + p.x;
            }
    }

For this code the assertion does not fail:

    IplImage * img=cvLoadImage("blah.jpg");
    int row=0,col=0;
    cv::Mat in(img);
    cv::Mat *mat=&in;
    cv::Point p;
    struct RGB { unsigned char b, g, r; };
    RGB *data;
    for( row = 0; row < mat->rows; ++row) 
    {
            for ( col = 0; col < mat->cols; ++col) 
            {
                 p.x=row,p.y=col;
                 assert((mat->step/mat->cols) == sizeof(RGB));
                 data = (RGB*)&mat->data;
                 data += p.y * mat->cols + p.x;
                 printf("Row=%dxCol=%d      b=%u g=%u r=%u\n",row,col,data->b,data->g,data->r);
                 wait_for_frame(1);
            }
    }

Because sizeof(RGB) != sizeof(float) , which is what you filled the matrix with here:

 CvMat* mat = cvCreateMat(300,300,CV_32FC1); 

CV_32FC1 means 1 component, 32-bit floating point. You probably want CV_8UC3 . See here or another OpenCV reference.

You can skip the entire IplImage misery if you use cv::Mat img = cv::loadImage("blah.jpg"); Also it is better to use row ptr for going through all the pixels.
It knows the jumps, so you don't have to worry!

From the refman:

If you need to process a whole row of a 2D array, the most efficient way is to get the pointer to the row first, and then just use the plain C operator []

Be aware that if you are loading bigger images which have "jumps" in their data, your code will not work. In your situation

cv::Mat img = cv::loadImage("blah.jpg");
const cv::Mat& M = img;
for(int i = 0; i < rows; i++) 
{
    const Vec3b* Mi = M.ptr<Vec3b>(i); 
    for(int j = 0; j < cols; j++)
    {
        const Vec3b& Mij = Mi[j];
        std::cout<<"Row="<<i<<"Col="<<j<<"\t";
        std::cout<<"b="<<Mij[0]<<" g="<<Mij[1]<<" r="<<Mij[2]<<std::endl;
    }
}

is the fastest correct way. Otherwise you could use M.at<Vec3b>(i,j) .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM