Qt界面加载网络摄像头,并实时显示,两种更新界面的方法

Qt界面加载网络摄像头,并实时显示,两种更新界面的方法

1、Qt界面加载网络摄像头,并实时显示,根据头文件中的宏定义来区分使用哪种方式。①Qt信号槽更新界面,②c语言回调方式更新界面
2、使用OpenCV、RTSP打开摄像头
3、适合初学者
4、本人使用Qt5.10.0、vs2015、opencv3.4.3,必须在运行根目录添加opencv动态库或将此库添加环境变量
5、里面涉及到一些单例模式、类静态成员的用法,后期再整理,供大家共同成长

 

代码:

********************LoadCamera.pro********************

#-------------------------------------------------
#
# Project created by QtCreator 2020-04-07T08:48:03
#
#-------------------------------------------------
 
QT       += core gui
 
greaterThan(QT_MAJOR_VERSION, 4): QT += widgets
 
TARGET = LoadCamera
TEMPLATE = app
 
# The following define makes your compiler emit warnings if you use
# any feature of Qt which has been marked as deprecated (the exact warnings
# depend on your compiler). Please consult the documentation of the
# deprecated API in order to know how to port your code away from it.
DEFINES += QT_DEPRECATED_WARNINGS
 
# You can also make your code fail to compile if you use deprecated APIs.
# In order to do so, uncomment the following line.
# You can also select to disable deprecated APIs only up to a certain version of Qt.
#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000    # disables all the APIs deprecated before Qt 6.0.0
 
 
SOURCES += \
        main.cpp \
    cframe.cpp \
    CReadVideo.cpp
 
HEADERS += \
    cframe.h \
    CReadVideo.h
 
INCLUDEPATH += \
D:\Softwares\opencv3.4.3\build\include\
D:\Softwares\opencv3.4.3\build\include\opencv\
D:\Softwares\opencv3.4.3\build\include\opencv2\
 
win32:CONFIG(release, debug|release): LIBS += -LD:/Softwares/opencv3.4.3/build/x64/vc15/lib/ -lopencv_world343
else:win32:CONFIG(debug, debug|release): LIBS += -LD:/Softwares/opencv3.4.3/build/x64/vc15/lib/ -lopencv_world343d

********************main.cpp********************

#include "cframe.h"
#include <QApplication>
 
int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    CFrame w;
    w.show();
 
    return a.exec();
}

********************cframe.h********************

#ifndef CFRAME_H
#define CFRAME_H
 
#include <QFrame>
#include <CReadVideo.h>
#include <QLabel>
 
class CFrame : public QFrame
{
    Q_OBJECT
 
public:
    explicit CFrame(QWidget *parent = 0);
    ~CFrame();
#ifdef USE_CALLBACK_1
    static void updateQImage(QImage image);
#endif
 
protected:
    //窗体改变大小
    void resizeEvent(QResizeEvent* event) override;
 
protected slots:
#ifdef USE_SIGNAL_SLOT
    //接收摄像头数据
    void slotRecviveQImage(const QImage& image);
#endif
 
private:
    //摄像头显示在的QLabel控件
    QLabel *m_LabelCameraView;
    //读视频线程
    CReadVideo* m_ReadVideo;
 
#ifdef USE_CALLBACK_1
    //单例、静态、回调使用的指针
    static CFrame* m_This;
#endif
};
 
#endif // CFRAME_H
 

********************cframe.cpp********************

#include "cframe.h"
#include <QDebug>
 
#ifdef USE_CALLBACK_1
CFrame *CFrame::m_This = nullptr;
#endif
CFrame::CFrame(QWidget *parent) :
    QFrame(parent)
{
    resize(960, 540);
    this->setMinimumWidth(192);
    this->setMinimumHeight(108);
#ifdef USE_CALLBACK_1
    m_This = this;
#endif
 
    m_LabelCameraView = new QLabel(this);
    m_LabelCameraView->setGeometry(0, 0, this->width(), this->height());
 
    //海康摄像头rtsp://admin:admin12345@192.168.10.100/h264/ch1/main/av_stream       ch2是辅码流
    //大华摄像头rtsp://admin:zhhh6052@192.168.2.5:554/cam/realmonitor?channel=1&subtype=0   subtype=1是辅码流
    m_ReadVideo = new CReadVideo(this);
    m_ReadVideo->setVideoAddress("rtsp://admin:zhhh6052@10.0.105.101:554/cam/realmonitor?channel=1&subtype=0");
#ifdef USE_CALLBACK_1
    m_ReadVideo->setUpdateMainThreadQImage(&CFrame::updateQImage);
#endif
#ifdef USE_SIGNAL_SLOT
    connect(m_ReadVideo, SIGNAL(sendQImage(const QImage)), this, SLOT(slotRecviveQImage(const QImage)));
#endif
    m_ReadVideo->start();
}
 
CFrame::~CFrame()
{
    m_ReadVideo->stop();
    delete m_ReadVideo;
    m_ReadVideo = nullptr;
    delete m_LabelCameraView;
    m_LabelCameraView = nullptr;
}
 
#ifdef USE_CALLBACK_1
void CFrame::updateQImage(QImage image)
{
    if(m_This->isHidden())
        return;
 
    m_This->m_LabelCameraView->setPixmap(QPixmap::fromImage(image));
}
#endif
 
void CFrame::resizeEvent(QResizeEvent *event)
{
    Q_UNUSED(event);
 
    //界面大小修改,则显示窗口跟随改变
    m_LabelCameraView->setGeometry(0, 0, this->width(), this->height());
}
 
#ifdef USE_SIGNAL_SLOT
void CFrame::slotRecviveQImage(const QImage& image)
{
    if(this->isHidden())
        return;
 
    m_LabelCameraView->setPixmap(QPixmap::fromImage(image));
}
#endif
 

********************creadvideo.h********************

#ifndef CREADVIDEO_H
#define CREADVIDEO_H
 
#include <QThread>
#include <opencv2/imgproc/imgproc.hpp>
#include <opencv2/videoio/videoio.hpp>
 
#define USE_SIGNAL_SLOT     //Qt信号槽更新界面
//#define USE_CALLBACK_1      //c语言回调方式更新界面
//#define USE_CALLBACK_2      //c++std回调方式更新界面
 
#ifdef USE_CALLBACK_1
typedef void (*pUpdateMainThreadQImage)(QImage image);
#endif
 
class CReadVideo : public QThread
{
    Q_OBJECT
public:
    explicit CReadVideo(QObject *parent = nullptr);
    ~CReadVideo();
    void stop();
#ifdef USE_CALLBACK_1
    void setUpdateMainThreadQImage(void* ptr);
#endif
 
    //设置网络摄像头地址
    void setVideoAddress(const QString& str);
 
#ifdef USE_SIGNAL_SLOT
signals:
    void sendQImage(const QImage&);
#endif
 
protected:
    virtual void run();
 
private:
    bool stopped;
 
    cv::VideoCapture m_VideoCapture;
    //Mat数据
    cv::Mat m_MatRead, m_MatRGB;
    //网络摄像头地址
    QString m_sVideoAddress;
 
#ifdef USE_CALLBACK_1
    //全局回调函数指针,用于回调主线程,更新界面
    pUpdateMainThreadQImage m_UpdateMainThreadQImage;
#endif
};
 
#endif // CREADVIDEO_H
 

********************creadvideo.cpp********************

#include "CReadVideo.h"
#include <QImage>
 
CReadVideo::CReadVideo(QObject *parent) : QThread(parent)
{
    stopped = false;
    m_sVideoAddress = "";
 
#ifdef USE_CALLBACK_1
    m_UpdateMainThreadQImage = nullptr;
#endif
}
 
CReadVideo::~CReadVideo()
{
    stopped = true;
    if(this->isRunning())
    {
        this->stop();
        //等待1500毫秒,线程退出
        for(int i=0; i<300; ++i)
        {
            if(stopped == false)
                break;
            //qDebug()<<"wait stop"<<i<<stopped;
            msleep(5);
        }
    }
}
 
void CReadVideo::stop()
{
    stopped = true;
}
 
#ifdef USE_CALLBACK_1
void CReadVideo::setUpdateMainThreadQImage(void *ptr)
{
    m_UpdateMainThreadQImage = static_cast<pUpdateMainThreadQImage>(ptr);
}
#endif
 
void CReadVideo::setVideoAddress(const QString& str)
{
    m_sVideoAddress = str;
}
 
void CReadVideo::run()
{
    stopped = false;
 
    while(!stopped)
    {
        try{
            //打开摄像头
            if(!m_VideoCapture.open(m_sVideoAddress.toStdString()))
            {
                sleep(6);
                continue;
            }
 
            while(!stopped)
            {
                if(!stopped)
                {
                    //读取摄像头视频
                    if(m_VideoCapture.read(m_MatRead))
                    {
                        //OpenCV使用BGR,QImage使用RGB,通道转换
                        cv::cvtColor(m_MatRead, m_MatRGB, CV_BGR2RGB);
                        //cv::Mat转QImage
                        QImage image = QImage(m_MatRGB.data, m_MatRGB.cols, m_MatRGB.rows, QImage::Format_RGB888);
 
#ifdef USE_SIGNAL_SLOT
                        //发送转换完成的QImage信号
                        if(!stopped)
                            emit sendQImage(image);
#endif
 
#ifdef USE_CALLBACK_1
                        m_UpdateMainThreadQImage(image);
#endif
                    }
                    else
                    {
                        break;
                    }
                }
                else
                {
                    break;
                }
            }
        }
        catch(QString sException)
        {
            Q_UNUSED(sException);
            sleep(60);
            continue;
        }
    }
 
    //m_VideoCapture.release();
    stopped = false;
}
 

 

整体代码,请见我的资源https://download.csdn.net/download/u011093735/15117317

  • 2
    点赞
  • 26
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: 要实时显示网络摄像头画面,可以使用Qt框架与网络协议结合来实现。 首先,需要使用Qt网络模块来建立与网络摄像头的连接。可以使用Qt提供的QTcpSocket类来进行TCP协议通信,或者使用QUdpSocket类进行UDP协议通信。根据网络摄像头的协议文档,配置socket的IP地址和端口号,以建立网络通信。 连接成功后,可以在Qt界面中创建一个用于显示画面的部件,例如QLabel或者QGraphicsView。然后,在网络通信中接收到摄像头传来的视频数据时,将数据解码为图像格式,例如JPEG或者RGB,然后在界面实时显示图像。 为了实现实时显示,需要使用Qt的多线程技术来分离网络数据的接收、解码和界面显示的操作。可以创建一个单独的线程用于接收网络数据,并将其存储到缓冲区中。另外一个线程用于从缓冲区中取出数据并进行解码操作,然后通过信号与界面线程通信,将解码后的图像显示界面上。 在图像显示过程中,可以添加一些额外的功能,例如实时调整图像的亮度、对比度、饱和度等参数,或者进行图像的旋转、缩放,以便更好地适应用户需求。 最后,在程序退出时,需要释放网络连接和停止线程的运行,以确保程序的正常退出和资源的释放。 总之,通过使用Qt网络模块、图像显示部件和多线程技术,结合网络摄像头的协议文档,可以实现在Qt界面实时显示网络摄像头画面。 ### 回答2: 在Qt实时显示网络摄像头画面可以通过以下步骤完成。 首先,需要创建一个Qt应用程序窗口作为显示画面的容器。可以使用Qt提供的窗口部件类,例如QMainWindow或QWidget等。 接下来,需要使用OpenCV或其他相关库来连接并获取网络摄像头视频流数据。可以使用OpenCV的VideoCapture类来打开网络摄像头,并使用其read()方法来连续获取每一帧的图像数据。 然后,将获取的每一帧图像数据转换成Qt能够识别的图像格式。可以使用Qt提供的QImage类或Qt的QPixmap类来保存图像数据。 最后,将转换后的图像数据显示Qt应用程序窗口中。可以使用Qt的QLabel类来显示图像,将QImage或QPixmap对象设置为QLabel的背景图像。 整个过程需要在一个循环中进行,以实现实时显示网络摄像头画面。可以使用Qt的定时器机制来控制每一帧图像的更新频率,从而实现实时显示效果。 总结起来,实时显示网络摄像头画面的关键步骤包括创建应用程序窗口,连接网络摄像头并获取视频流数据,转换图像数据格式,以及在Qt窗口中显示图像数据。通过这些步骤,可以实现实时显示网络摄像头画面的功能。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值