0

I try the code below to serialize and deserialize a cv::Mat object. It just records all the uchars into a ostringstream then converts it to string to serialize. Then I deserialize this string using istringstream and save all the uchars into a Mat object. Mat type CV_8UC3 is legit, I checked it by using the function in this answer. 8UC3 is the channel of the test Mat I give as parameter. I know this is probably a lame way to serialize, so I'm open to better ideas. Anyway the I only get 25 % ish part of the picture. The rest is missing. And I get a weird color distortion in the middle. Output and input images are below the code. If you need anymore details feel free to ask.

void dbop::serializeMat(cv::Mat operand) {

std::ostringstream srlzstrstream;
srlzstrstream << operand.rows << " " << operand.cols << " " ;
for(int i = 0; i < operand.rows; i++)
    for (int j = 0; j < operand.cols; j++)
        srlzstrstream << operand.at<uchar>(i, j);

std::string srlzdstr = srlzstrstream.str();

uchar uchoper;
int row, col;
std::istringstream desrlzstrstream(srlzdstr);

desrlzstrstream >> row;
desrlzstrstream >> col;
cv::Mat matoper(row, col, CV_8UC3);

for (int i = 0; i < row; i++) {
    for (int j = 0; j < col; j++) {
        desrlzstrstream>> uchoper;
        matoper.at<uchar>(i, j) = uchoper;
    }
}

return;
}

This is the input image

This is the output image

EDIT

rafix07 after following your advice I found an alternative way that has 3 bytes per pixel. Now I get the complete picture but color distortion (or whatever it is called) is now worse then ever. Top 10% ish of the output image is fine but below that it goes to hell. See the image below code.

void dbop::serializeMat(cv::Mat operand) {
std::ostringstream srlzstrstream;
cv::uint8_t* pixelPtr = (uint8_t*)operand.data;
int cn = operand.channels();
cv::Scalar_<uint8_t> bgrPixel;

srlzstrstream << operand.rows << " " << operand.cols << " ";
for (int i = 0; i < operand.rows; i++) {
    for (int j = 0; j < operand.cols; j++) {
        bgrPixel.val[0] = pixelPtr[i * operand.cols * cn + j * cn + 0]; // B
        bgrPixel.val[1] = pixelPtr[i * operand.cols * cn + j * cn + 1]; // G
        bgrPixel.val[2] = pixelPtr[i * operand.cols * cn + j * cn + 2]; // R
        srlzstrstream << bgrPixel.val[0] << bgrPixel.val[1] << bgrPixel.val[2];
    }
}
std::string srlzdstr = srlzstrstream.str();
uchar uchoper1, uchoper2, uchoper3;
int row, col;
std::istringstream desrlzstrstream(srlzdstr);

desrlzstrstream >> row;
desrlzstrstream >> col;
cv::Mat matoper(row, col, CV_8UC3);

for (int i = 0; i < row; i++) {
    cv::Vec3b* ptr = matoper.ptr<cv::Vec3b>(i);
    for (int j = 0; j < col; j++) {
        desrlzstrstream >> uchoper1;
        desrlzstrstream >> uchoper2;
        desrlzstrstream >> uchoper3;
        ptr[j] = cv::Vec3b(uchoper1, uchoper2, uchoper3);
    }
}
return;
}

Output image after edit

One Bad Student
  • 160
  • 2
  • 9
  • 1
    You write only one byte from input color image? Your output is CV_8UC3, 3 channels. It doesn't match each other. – rafix07 Feb 11 '20 at 14:47
  • @rafix07 You are right, after your suggestion I found a better way that represents 3 byte per pixel but problem is different now. Check the edit. – One Bad Student Feb 11 '20 at 16:06

1 Answers1

1

Suppose you have:

uchar ch = 10;
ostringstream os;
os << ch;

when you do:

std::cout << "[" << os.str() << "]" << std::endl;

you will see:

[
]

because ostringstream treats all values stored in (unsigned) char as characters (in above case, 10 represents newline, and this newline character is put into stream instead of its numeric value). You have to write / read integers with at least 16 bits precision. And the other issue, when pushing into the stream you have to add whitespaces between values.

So, first update is:

srlzstrstream << (int)bgrPixel.val[0] << " " << (int)bgrPixel.val[1] << " " << (int)bgrPixel.val[2] << " ";

and the next one:

uint16_t uchoper1, uchoper2, uchoper3;
rafix07
  • 20,001
  • 3
  • 20
  • 33
  • Yes that exactly solved it. I thought casting them to something else would cause data loss or whatever but I guess I was just wrong. :D Thanks man! – One Bad Student Feb 11 '20 at 16:39