Ask Your Question
1

c++ convert uchar * to opencv mat

asked 2015-02-22 15:23:17 -0600

Tumelo M. Motloutsi gravatar image

I have converted a cv::Mat object to uchar *

uchar *DisplayImage::MatToBytes(cv::Mat image)
{
    //class data members
image_rows = image.rows;
image_cols = image.cols;
image_type  = image.type();

    int image_size = image.total() * image.elemSize();
    uchar * image_uchar = new uchar[image_size];

    std::vector<uchar> v_char;
    for(int i = 0; i < image.rows; i++)
    {
        for(int j = 0; j < image.cols; j++)
        {
            v_char.push_back(*(uchar*)(image.data+ i + j));
        }
    }
    //image_uchar is a class data member
    image_uchar = &v_char[0];

    //cvWaitKey(5000);
    return image_uchar;
}

I now want to convert the uchar* back to Mat object. I tried using the Mat clone function but I don't really understand all the parameters for the default Mat constructor. And then I read somewhere that I can just use the default Mat constructor but I don't know what that last parameter (size_t step) means.

cv::Mat DisplayImage::BytesToMat()
{
    cv::Mat img =   cv::Mat(image_rows,image_cols,CV_16UC1,image_byte,0); //I  am not sure about the last parameter here

    cv::namedWindow("MyWindow");
    cv::imshow("MyWindow",img);
    cvWaitKey(500);
    return img;
}

How do you convert uchar * back to Mat object? The image is a colour image by the way

edit retag flag offensive close merge delete

Comments

I don't know your concerns, but a Mat is, in case of a CV_8UC, already a uchar array. You get the address to the first element by using

uchar *image_uchar = img.data;

Consider that in case of a 3 channel image data storage is: blue[0][0], green[0][0], red[0][0], blue[0][1], green[0][1], red[0][1],... Check out: How the image matrix is stored in the memoryt

When you want a Mat out of a uchar array use

Mat byteImage = Mat(rows, cols, CV_8UC3, image_uchar);

in case of a 3 channel byte image. It isn't necessary to specify size_t step because it is AUTO_STEP by default.

matman gravatar imagematman ( 2015-02-22 16:24:12 -0600 )edit

Thanks, the link was 'slots' helpful although there parts I find confusing there but I will read some more as I am still leaerning

Tumelo M. Motloutsi gravatar imageTumelo M. Motloutsi ( 2015-02-23 01:32:01 -0600 )edit

1 answer

Sort by ยป oldest newest most voted
1

answered 2015-02-22 16:39:32 -0600

Guanta gravatar image

Sorry to say, but what you do in your MatToBytes(cv::Mat image) will defenitely end in a memory leak (you are allocating memory on the stack - the local variable v_char - and will get lost after you end your function). Why not just use memcpy (make sure your data is continuos (isContinuous())?!

cv::Mat img = cv::Mat(image_rows,image_cols,CV_16UC1,image_byte) looks fine to me, however note that a typical image has type CV_8UC1 not CV_16UC1 (and for color CV_8UC3), but I guess that was intentionally.

edit flag offensive delete link more

Comments

Thanks for your response. I have made modifications as below

uchar *DisplayImage::MatToBytes(cv::Mat image)
{
        //class data members of ints
    image_rows = image.rows;
    image_cols = image.cols;
    image_type  = image.type();

    int image_size = image.total() * image.elemSize();
    uchar * image_uchar = new uchar[image_size];
    std::memcpy(image_uchar,image.data,image_size * sizeof(uchar));
    return image_uchar;
}

cv::Mat DisplayImage::BytesToMat()
{
    cv::Mat img(image_rows,image_cols,image_type,image_uchar,cv::Mat::AUTO_STEP);
    return img;
}
Tumelo M. Motloutsi gravatar imageTumelo M. Motloutsi ( 2015-02-23 01:28:45 -0600 )edit
2

@Tumelo M. Motloutsi , your code still contain leak in MatToBytes you can avoid the crach as follow

int DisplayImage::MatToBytes(cv::Mat image, uchar **  pimage_uchar)
{
uchar * image_uchar  = * pimage_uchar;
        //class data members of ints
    image_rows = image.rows;
    image_cols = image.cols;
    image_type  = image.type();

    int image_size = image.total() * image.elemSize();
    image_uchar = new uchar[image_size];
    std::memcpy(image_uchar,image.data,image_size * sizeof(uchar));
    return 1;
}

and when you finsh using image_char you should free the memory by using the following function

void DisplayImage::FreeImage_Char(uchar ** pimage_uchar) { uchar * image_char = *pimage_uchar; delete [] image_char;}

essamzaky gravatar imageessamzaky ( 2015-02-23 02:38:12 -0600 )edit

Just another note: please also add sth like: CV_Assert( image.isContinuous() );

Guanta gravatar imageGuanta ( 2015-02-23 07:08:03 -0600 )edit

Question Tools

1 follower

Stats

Asked: 2015-02-22 15:23:17 -0600

Seen: 28,675 times

Last updated: Feb 22 '15