Convert a string of bytes to cv::mat
Asked Answered
C

4

11

I need to implement a function that receives a string containing the bytes of an image (received via boost socket connection) and converts the info into an OpenCV cv::Mat.

I also know the width and height of the image and its size in bytes. My function looks like this:

void createImageFromBytes(const std::string& name, std::pair<int,int> dimensions, const std::string& data)
{
   int width,height;
   width = dimensions.first;
   height = dimensions.second;
   //convert data to cv::Mat image

   std::string filepng = DATA_PATH"/" + name +".png";
   imwrite(filepng, image);
}

Which is the best method for doing this? Does OpenCV has a constructor for Mat from a string?

Chimney answered 4/12, 2012 at 14:50 Comment(1)
Any updates on this one?Marinara
C
19

OpenCV Mat has a constructor from vector<byte>, but this is not so intuitive. You need to convert from string to vector this way first:

std::vector<byte> vectordata(data.begin(),data.end());

Then you can create a cv::Mat from the vector:

cv::Mat data_mat(vectordata,true);

You also need to decode the image (check documentation for which types are allowed, png, jpg, depending on the OpenCV version)

cv::Mat image(cv::imdecode(data_mat,1)); //put 0 if you want greyscale

Now you can check if the resulting size of the image is the same as the one you sent:

cout<<"Height: " << image.rows <<" Width: "<<image.cols<<endl;
Confessedly answered 4/12, 2012 at 14:56 Comment(1)
What is byte? Is it std::byte?Providing
I
2

Easy to trip here as the image may have null characters and any c function handling string will see null as string end

Read the image

cv::Mat image;
    image = cv::imread("../test/image.png", CV_LOAD_IMAGE_COLOR);

Convert to Bytes (this is just working code, not checked for leaks)

int dataSize = image.total() * image.elemSize();
//convert to bytes
std::vector<char> vec(dataSize);
memcpy(&vec[0], reinterpret_cast<char *>(image.data), dataSize);
std::string test2(vec.begin(), vec.end());

Test and see if conversion works

//test
cv::Mat data_mat(height,width,CV_8UC3,const_cast<char*>(test2.c_str()));
imwrite("out2.png", data_mat);
Intercalation answered 30/7, 2018 at 5:42 Comment(0)
F
1

If the data in the string is raw pixels (rather than a Jpeg/png etc) you can create the cv::mat directly

// assuming an RGB image in bytes              
cv::Mat mat(height,width,CV_8UC3,string.data());   
Forras answered 4/12, 2012 at 15:48 Comment(2)
Not to nit-pick, but aren't height and rows the same thing?Lalise
I'm getting errors on compilation complaining that there's no matching constructor for this use of cv::Mat. Possibly updates to opencv since your post have broken your solution?Bawd
M
0

Here is my improved solution of Jav_Rock, the problem is that is not clear to use vector (byte type is not defined in c++, i didn't found that), instead of that, use vector, here is a example code

int func(char * pfile){
string strfile = pfile;
std::vector<unsigned char> vectordata(strfile.begin(),strfile.end());
Mat data_mat(vectordata, true);
Mat graySacleFrame = imdecode(data_mat, 0); //PGM image
...
}
Murrelet answered 24/7, 2016 at 3:57 Comment(1)
Cried in std::byteProviding

© 2022 - 2024 — McMap. All rights reserved.