前言
因为项目需要,现在需要使用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
#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;}elsereturn -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 imgzmq::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
#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
待完善。