红胖子(红模仿)的博文大全:开发技术集合(包含Qt实用技术、树莓派、三维、OpenCV、OpenGL、ffmpeg、OSG、单片机、软硬结合等等)

 

需求

        有10台服务器,每台8路摄像头,8路拼接处理后单个服务器输出8*1920*1080的图片数据,每台服务器输出各自的八路,实现缩放拽拖等。

 

ReadMe

案例分享:Qt的80路显示超大屏幕拼接(十台服务器,每台八路摄像头)方案和Demo_C/S

 

最终采用的方案

        步骤一:客户端获取每个服务器在本地的实际rect(每个服务器在本地的原始图片拼接范围);

        步骤二:依据缩放比例系数和鼠标的位置计算出rectVirtual(按照指定点缩小放大后的图片拼接范围);

        步骤三:每个服务器所处的rectVirtual与实际显示的窗口rect()取交集,更新的每个服务器显示的范围;

        步骤四:分别组装获取指令(一个线程负责一个块区域),

                     将获取指令(x,y,width,height,scale)发送(Json);

        步骤五:接收更新显示范围后的协议数据;

        步骤六:解析协议获取rgb888数据:总长度(包括总长度4字节)(4字节)+ 图像宽度(2字节)+ 图像原始高度(2字节)+ 显示宽度(2字节) + 显示高度(2字节) + 图像数据(n字节);

        步骤七:使用服务器获取的显示数据刷新对应的显示区域,重复步骤二。

        注意:软件模拟时间主要耗在服务器对图像的变换,使用本地硬解码或者库之后(直接调库)或者从服务器获取,其时间达到20ms左右,可达到理想效果。

 

Demo

        下载地址:javascript:void(0)

 

演示图

案例分享:Qt的80路显示超大屏幕拼接(十台服务器,每台八路摄像头)方案和Demo_超大图像_02

案例分享:Qt的80路显示超大屏幕拼接(十台服务器,每台八路摄像头)方案和Demo_拼接图像处理_03

案例分享:Qt的80路显示超大屏幕拼接(十台服务器,每台八路摄像头)方案和Demo_拼接服务器_04

案例分享:Qt的80路显示超大屏幕拼接(十台服务器,每台八路摄像头)方案和Demo_拼接图像处理_05

案例分享:Qt的80路显示超大屏幕拼接(十台服务器,每台八路摄像头)方案和Demo_拼接图像处理_06

 

客户端关键代码(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