若该文为原创文章,转载请注明原文出处
本文章博客地址:https://blog.csdn.net/qq21497936/article/details/79577035
各位读者,知识无穷而人力有穷,要么改需求,要么找专业人士,要么自己研究
红胖子(红模仿)的博文大全:开发技术集合(包含Qt实用技术、树莓派、三维、OpenCV、OpenGL、ffmpeg、OSG、单片机、软硬结合等等)持续更新中…(点击传送门)
合作案例专栏:案例分享(体验Demo可下载,只定制)
需求
有10台服务器,每台8路摄像头,8路拼接处理后单个服务器输出8*1920*1080的图片数据,每台服务器输出各自的八路,实现缩放拽拖等。
ReadMe
最终采用的方案
步骤一:客户端获取每个服务器在本地的实际rect(每个服务器在本地的原始图片拼接范围);
步骤二:依据缩放比例系数和鼠标的位置计算出rectVirtual(按照指定点缩小放大后的图片拼接范围);
步骤三:每个服务器所处的rectVirtual与实际显示的窗口rect()取交集,更新的每个服务器显示的范围;
步骤四:分别组装获取指令(一个线程负责一个块区域),
将获取指令(x,y,width,height,scale)发送(Json);
步骤五:接收更新显示范围后的协议数据;
步骤六:解析协议获取rgb888数据:总长度(包括总长度4字节)(4字节)+ 图像宽度(2字节)+ 图像原始高度(2字节)+ 显示宽度(2字节) + 显示高度(2字节) + 图像数据(n字节);
步骤七:使用服务器获取的显示数据刷新对应的显示区域,重复步骤二。
注意:软件模拟时间主要耗在服务器对图像的变换,使用本地硬解码或者库之后(直接调库)或者从服务器获取,其时间达到20ms左右,可达到理想效果。
Demo
下载地址:https://download.csdn.net/download/qq21497936/10289809
演示图
客户端关键代码(ImageWidget控件)
imagewidget.h
#ifndef IMAGEWIDGET_H #define IMAGEWIDGET_H #include <QWidget> #include <QThread> #include <QRectF> #include "tcpclient.h" #include <QElapsedTimer> /************************************************************\ * 类名:ImageWidget * 描述:1-10路固定19200*1080图像拼接 * 使用: * 1.构建一个ImageWidget类 * 2.设置主机地址setHostAddreess,填入一一对应的服务器ip地址list和port端口list * 3.调用start * 函数: * isRunning() - 是否在运行 * setHostAddreess() - 设置服务器地址,如:127.0.0.1:20001,127.0.0.1:20002,则传入QList("127.0.0.1","127.0.01"),QList(20001,20002) * start() - 开启运行 * stop() - 停止运行 * 作者:红模仿 QQ:21497936 * 版本 日期 描述 * v1.0 2018年3月12日 已优化 \************************************************************/ namespace Ui { class ImageWidget; } class ImageWidget : public QWidget { Q_OBJECT public: explicit ImageWidget(QWidget *parent = 0); ~ImageWidget(); bool isRunning(); signals: void signalfinished(); public slots: void start(); void stop(); void setHostAddreess(QList<QString> listIp, QList<quint16> listPort); void init(); protected slots: void recvOneImage(int index, QByteArray& data, int fullWidth, int fullHeight, int width, int height, int time); protected: void paintEvent(QPaintEvent *event) override; void resizeEvent(QResizeEvent *event) override; void mousePressEvent(QMouseEvent *event) override; void mouseMoveEvent(QMouseEvent *event) override; void wheelEvent(QWheelEvent *event) override; private slots: void finished(); private: Ui::ImageWidget *ui; QList<TcpClient *> _listTcpClient; QList<QThread *> _listTcpClientThread; bool _ok; QPoint _pointLast; double _add_scale_step; double _dec_scale_step; double _scale; QList<QRectF> _listRectRangeFullImage; // 图片的实际尺寸 QList<QRectF> _listRectRangeFullImageVirtual; // 虚拟显示框框 QList<QRectF> _listRectRangeGetImage; // 图像数据 QList<QRectF> _listRectRangeImageOldShow; // 旧区域 QList<QRectF> _listRectRangeImageShow; // 正常情况下的需要显示的部分 QList<QPixmap *> _listPixmap; bool _initRectRangeFullImageVirtual; QElapsedTimer _time; int _serverNumber; QList<QString> _listIp; QList<quint16> _listPort; QElapsedTimer _timerInverval; }; #endif // IMAGEWIDGET_H
服务器代码
mainwindow.h
#ifndef MAINWINDOW_H #define MAINWINDOW_H #include <QMainWindow> #include <QImage> #include <QTcpServer> #include <QTcpSocket> #include <QByteArray> #define SCALE_BASE (1000) class QPaintEvent; namespace Ui { class MainWindow; } class MainWindow : public QMainWindow { Q_OBJECT public: explicit MainWindow(QWidget *parent = 0); ~MainWindow(); protected slots: void newConnection(); void readyRead(); void doImage(int x, int y, int width, int height, double scale); void doImage(int x, int y, int width, int height, int vx, int vy, int vWidth, int vHeight); protected: void paintEvent(QPaintEvent *event) override; private slots: void on_pushButton_clicked(); private: Ui::MainWindow *ui; QImage _image; QTcpServer *_pTcpServer; QTcpSocket * _pTcpSocket; QByteArray _byteArrayJpg; }; #endif // MAINWINDOW_H
若该文为原创文章,转载请注明原文出处
本文章博客地址:https://blog.csdn.net/qq21497936/article/details/79577035