通过QT WebSocket将OpenCV Mat Image发送到HTML客户端

Send opencv Mat image through Qt websocket to HTML client

本文关键字:HTML 客户端 Image Mat QT WebSocket OpenCV 通过      更新时间:2023-10-16

我正在尝试使用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;
};

我认为大多数问题都在服务器中,因为我从图像中获得的base64序列与我从在线转换器image/base64中获得的base64序列不同。在客户端,我在控制台中收到此错误,没有显示任何内容:

数据:图像/png; base64,[对象arraybuffer]:1获取 数据:图像/png; base64,[对象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是使用此代码完成的:

encode/decode base64

服务器中的这一行:

imgIn = cv::imread("/home/me/color.png",CV_LOAD_IMAGE_COLOR);

解码 png格式的图像,并将其作为像素数据的负载(加上您不考虑的一些行填充物的负载(,请参见下文(。这就是您的基本64编码。

客户端中的这一行:

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,则不必担心。