c++ - 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;
}
解决方案
假设你有:
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;
推荐阅读
- tomcat - Intellij IDEA - 在 tomcat 中为多个模块定义单独的上下文根
- php - 将 MySQL 数据转换为 JSON 并包含 MySQL 计数
- apache - 301 重定向,在 url 中使用 %0A
- r - r - 来自 crosswalkr 的 renamefrom 函数返回 0 列
- javascript - Bootstrap 4 通过 JavaScript 切换按钮上的图标
- python-3.x - 无法使用 Selenium 和 Python3 在表单中找到元素
- c# - 无法使用 moq 对 API 控制器进行单元测试。我哪里错了?
- angular - 如何在 Angular 中按 2 引用表单元素?
- html - 在 HTML 中播放实时流媒体 .wav 文件
- rust - 将属性应用于宏扩展