我正在尝试使用 Qt 5.7 在 c++ 中编写一个应用程序,基本上它应该是一个 websocket 服务器,为此使用 qwebsocket,能够将用 opencv 制作的图像发送到 HTML 客户端。我想要做的是在 base64 中对图像进行编码,传输并在客户端将编码后的字符串放入图像标签的 src 中。 只是为了测试,我可以正确地发送/接收短信,所以 websocket 架构正在运行,但我在图像方面遇到了一些问题。这是我的代码片段:
服务器
cv::Mat imgIn;
imgIn = cv::imread("/home/me/color.png",CV_LOAD_IMAGE_COLOR);
QByteArray Img((char*)(imgIn.data),imgIn.total()*imgIn.elemSize());
QByteArray Img64 = Img.toBase64();
pClient->sendBinaryMessage(Img64);
客户端
<img id="ItemPreview" src="" style="border:5px solid black" />
....
websocket.binaryType = "arraybuffer";
websocket.onmessage = function (evt) {
console.log( "Message received :", evt.data );
document.getElementById("ItemPreview").src = "data:image/png;base64," + evt.data;
};
我觉得大部分问题出在Server端,因为我从image中得到的base64序列和我从网上转换器image/base64中得到的序列不一样。 在客户端上,我在控制台中收到此错误,但未显示任何内容:
data:image/png;base64,[object ArrayBuffer]:1 GET data:image/png;base64,[object ArrayBuffer] net::ERR_INVALID_URL
有什么提示吗?
解决方案
感谢建议,我可以提供工作代码:
服务器
imgIn = cv::imread("/home/me/color.png", CV_LOAD_IMAGE_UNCHANGED);
std::vector<uchar> buffer;
cv::imencode(".png",imgIn,buffer);
std::string s = base64_encode(buffer.data(),buffer.size());
pClient->sendTextMessage(QString::fromStdString(s));
客户端
删除了这一行:
websocket.binaryType = "arraybuffer";
服务器中的base64编码是用这段代码完成的:
最佳答案
服务器中的这一行:
imgIn = cv::imread("/home/me/color.png",CV_LOAD_IMAGE_COLOR);
解码 PNG 格式的图像,并将其作为像素数据加载放入内存中(可能还有一些您没有考虑的行填充,见下文)。这就是你的 base64 编码。
客户端中的这一行:
document.getElementById("ItemPreview").src = "data:image/png;base64," + evt.data;
需要 PNG 图像,但这不是您要发送的图像;你刚刚推出了一大堆原始像素数据,没有尺寸、步幅、格式信息或任何其他信息。
如果您的客户想要 PNG,您将不得不使用类似 imencode
的格式。将 PNG 数据写入内存缓冲区,然后对其进行 base64 编码。
另一件需要注意的重要事情是解码图像可能有行填充......为了内存对齐目的,每行末尾有几个字节。因此,每个图像行的实际长度可能超过图像宽度乘以每个像素的大小(以字节为单位)。这意味着这个操作:
QByteArray Img((char*)(imgIn.data),imgIn.total()*imgIn.elemSize());
事实上,可能不会将整个图像缓冲区包装在您的QByteArray
中。有多种方法可以检查图像的步幅/步长,但您最好阅读 cv::Mat
文档,因为我不值得在这里重复它们。这仅在您进行原始字节级图像处理时才重要,就像您在这里一样。如果您使用 imencode
,则无需担心这一点。
关于html - 通过Qt websocket发送opencv Mat图像到HTML客户端,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44395002/