【问题标题】:cv::Mat to std::string serialization and deserialization giving faulty resultcv::Mat 到 std::string 序列化和反序列化给出错误结果
【发布时间】:2020-05-27 00:06:12
【问题描述】:

我尝试使用下面的代码来序列化和反序列化 cv::Mat 对象。它只是将所有 uchars 记录到 ostringstream 中,然后将其转换为字符串以进行序列化。然后我使用 istringstream 反序列化这个字符串并将所有 uchars 保存到一个 Mat 对象中。垫子类型 CV_8UC3 是合法的,我使用this 答案中的函数进行了检查。 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;
}

This is the input image

This is the output image

编辑

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

Output image after edit

【问题讨论】:

  • 您只从输入的彩色图像中写入一个字节?您的输出是 CV_8UC3,3 个通道。不匹配。
  • @rafix07 你是对的,根据你的建议,我找到了一种更好的方法,它代表每像素 3 个字节,但现在问题不同了。检查编辑。

标签: c++ image opencv


【解决方案1】:

假设你有:

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

当你这样做时:

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

你会看到:

[
]

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

所以,第一次更新是:

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

还有下一个:

uint16_t uchoper1, uchoper2, uchoper3;

【讨论】:

  • 是的,这完全解决了它。我认为将它们转换为其他东西会导致数据丢失或其他什么,但我想我错了。 :D 谢谢老兄!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2018-03-22
  • 1970-01-01
  • 2016-08-18
  • 2014-12-31
  • 2018-06-14
  • 2014-05-19
  • 1970-01-01
相关资源
最近更新 更多