前言
因为项目需要,现在需要使用ZeroMq去实现摄像头视频数据的传输,尝试了不少方法,以下是一些成功的汇总,定时更新:
参考文章:
ZeroMQ+OpenCV实现视频网络传输_zmq视频传输-CSDN博客
这个代码有点问题,需要微调,具体看我的代码方法一。
因为我的开发环境是QT,以下以ubuntu20.04,QT5.12为例:
方法一:使用opencv和zeromq
原理:
使用了opencv的接收摄像头数据,以及imencode和imdecode进行jpg的编解码。
发送端:
pro文件:
增加内容:
LIBS += /usr/local/lib/libzmqpp-static.a -lzmq
#opencv:******************************************
CONFIG += link_pkgconfig
PKGCONFIG += opencv4
LIBS += -L/usr/lib/x86_64-linux-gnu/ -lopencv_core -lopencv_highgui -lopencv_imgproc -lopencv_imgcodecs -lopencv_videoio
INCLUDEPATH += /usr/include/opencv4/opencv2
#*************************************************
main.cpp
cpp
#include <zmq.hpp>
#include <iostream>
#include <opencv2/highgui.hpp>
#include <opencv2/opencv.hpp>
int main()
{
zmq::context_t context(1);
zmq::socket_t socket(context, zmq::socket_type::pub);
socket.bind("tcp://*:5555");
cv::VideoCapture cap(0);
if (cap.isOpened())
{
std::cout << "摄像头已打开" << std::endl;
std::cout << "图像宽度" << cap.get(cv::CAP_PROP_FRAME_WIDTH) << std::endl;
std::cout << "图像高度" << cap.get(cv::CAP_PROP_FRAME_HEIGHT) << std::endl;
}
else
return -1;
cv::Mat frame;
while (cap.read(frame))
{
cv::Size dstSize = cv::Size(1280,960);
cv::Mat dstFrame;
cv::resize(frame, dstFrame, dstSize);
std::vector<uint8_t> imageBuffer;
std::vector<int> compress_params;
compress_params.push_back(cv::IMWRITE_JPEG_QUALITY);
compress_params.push_back(40);//压缩为原图像的x%,x in [0,100]
cv::imencode(".jpg", dstFrame, imageBuffer, compress_params);
//send img
zmq::message_t msg(imageBuffer.size());
memcpy(msg.data(), imageBuffer.data(), imageBuffer.size());
socket.send(msg, zmq::send_flags::dontwait);
std::cout<<"send image, len:"<<imageBuffer.size() << std::endl;
//cv::imshow("pub", dstFrame);
cv::waitKey(1000 / cap.get(cv::CAP_PROP_FPS));
}
return 0;
}
接收端:
pro文件:
同发送端相同。
main.cpp
cpp
#include <iostream>
#include <string>
#include <zmq.hpp>
#include <opencv2/highgui.hpp>
#include <opencv2/opencv.hpp>
using namespace std;
int main (int argc, char *argv [])
{
zmq::context_t context(1);
zmq::socket_t socket(context, zmq::socket_type::sub);
socket.connect("tcp://localhost:5555"); // 可以替换为其他地址
socket.setsockopt(ZMQ_SUBSCRIBE, "", 0); // 设置订阅空字符串以接收所有消息
cv::Mat frame;
while (true) {
zmq::message_t msg;
auto ok = socket.recv(msg, zmq::recv_flags::dontwait);
if (ok) {
std::vector<uint8_t> buffer(static_cast<uint8_t*>(msg.data()), static_cast<uint8_t*>(msg.data()) + msg.size());
std::cout << "Received image, len: " << msg.size() << std::endl;
// 解码图像
frame = cv::imdecode(buffer, cv::IMREAD_COLOR);
cv::imshow("sub", frame);
cv::waitKey(1);
}
}
return 0;
}
方法二:gstreamer和zeromq,h264
待完善。