首页 > 解决方案 > cv::Mat 到 std::string 序列化和反序列化给出错误结果

问题描述

我尝试使用下面的代码来序列化和反序列化 cv::Mat 对象。它只是将所有 uchars 记录到 ostringstream 中,然后将其转换为字符串以进行序列化。然后我使用 istringstream 反序列化这个字符串并将所有 uchars 保存到一个 Mat 对象中。垫子类型 CV_8UC3 是合法的,我使用这个答案中的函数检查了它。8UC3 是我作为参数给出的测试垫的通道。我知道这可能是一种蹩脚的序列化方式,所以我愿意接受更好的想法。无论如何,我只得到图片的 25 % ish 部分。其余的都不见了。我在中间得到一个奇怪的颜色失真。输出和输入图像位于代码下方。如果您需要更多详细信息,请随时询问。

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;
}

这是输入图像

这是输出图像

编辑

rafix07 在听从你的建议后,我找到了一种每像素 3 个字节的替代方法。现在我得到了完整的图片,但颜色失真(或任何它被称为)现在比以往任何时候都更糟。输出图像的前 10% ish 很好,但低于它就惨了。请参阅下面的代码图像。

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;
}

编辑后输出图像

标签: c++imageopencv

解决方案


假设你有:

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

当你这样做时:

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

你会看见:

[
]

因为ostringstream将存储在 (unsigned) 中的所有值char视为字符(在上述情况下,10表示换行符,并且此换行符被放入流中而不是其数值)。您必须以至少 16 位精度写入/读取整数。另一个问题是,当推入流时,您必须在值之间添加空格。

所以,第一个更新是:

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

下一个:

uint16_t uchoper1, uchoper2, uchoper3;

推荐阅读