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
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
#include
#include
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
#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:[email protected]/h264/ch1/main/av_stream ch2是辅码流
//大华摄像头rtsp://admin:[email protected]:554/cam/realmonitor?channel=1&subtype=0 subtype=1是辅码流
m_ReadVideo = new CReadVideo(this);
m_ReadVideo->setVideoAddress("rtsp://admin:[email protected]: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
#include
#include
#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
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"<msleep(5);}}}void CReadVideo::stop(){stopped = true;}#ifdef USE_CALLBACK_1void CReadVideo::setUpdateMainThreadQImage(void *ptr){m_UpdateMainThreadQImage = static_cast(ptr); }#endifvoid 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转QImageQImage 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_1m_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