一.在Qt添加Opencv的环境
如何在ubuntu下安装opencv网上有很多的教程了,这里就不细说了,将安装完毕的opencv添加到Qt中很简单,在工程文件中个的.pro中添加三行即可,如下图所示。
INCLUDEPATH += /usr/local/include/opencv4 \
/usr/local/include/opencv4/opencv2
LIBS += /usr/local/lib/libopencv_*.so.4.5.5
然后就可以调用opencv的库了,
#include <opencv2/imgproc/imgproc.hpp>
#include <opencv2/core/core.hpp>
#include <opencv2/objdetect/objdetect.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <videoio.hpp>
这一步就完成了Qt在opencv中的调用。
二.实现摄像头实时监控
由于要实现的是多个摄像头同时实时监控,所以需要在子线程中读取视频流,解析编码,图片转化,在主线程将每帧图片显示出来就可以了。
效果图如下:
实现的代码如下:
1.先在主程序中添加多线程:
QThread *cam1;
Cam1 *MyCam1;
QThread *cam2;
Cam2 *MyCam2;
QThread *cam3;
Cam3 *MyCam3;
QThread *cam4;
Cam4 *MyCam4;
MyCam1 = new Cam1;
cam1 = new QThread(this);
MyCam1->moveToThread(cam1);
cam1->start();
connect(this,SIGNAL(sendCamDispay()), MyCam1, SLOT(GetCamDisplay()));
connect(MyCam1,SIGNAL(SendPic(QImage)),this,SLOT(CamShow(QImage)));
MyCam2 = new Cam2;
cam2 = new QThread(this);
MyCam2->moveToThread(cam2);
cam2->start();
connect(this,SIGNAL(sendCamDispay2()), MyCam2, SLOT(GetCamDisplay2()));
connect(MyCam2,SIGNAL(SendPic2(QImage)),this,SLOT(CamShow2(QImage)));
MyCam3 = new Cam3;
cam3 = new QThread(this);
MyCam3->moveToThread(cam3);
cam3->start();
connect(this,SIGNAL(sendCamDispay3()), MyCam3, SLOT(GetCamDisplay3()));
connect(MyCam3,SIGNAL(SendPic3(QImage)),this,SLOT(CamShow3(QImage)));
MyCam4 = new Cam4;
cam4 = new QThread(this);
MyCam4->moveToThread(cam4);
cam4->start();
connect(this,SIGNAL(sendCamDispay4()), MyCam4, SLOT(GetCamDisplay4()));
connect(MyCam4,SIGNAL(SendPic4(QImage)),this,SLOT(CamShow4(QImage)));
2.读取视频流:
我用的是CPU解码视频流,也就是软解码
QString str_name = QString("rtsp://admin:admin123456@%1:554/av0_0").arg(camIP[0]);
str1 = str_name.toStdString();
video=VideoCapture(str1);
如果CPU负荷太高的话,可以用GPU解码视频流,也就是硬解码
QString str_name = QString("rtsp://admin:admin123456@%1:554/av0_2").arg(camIP[0]);
// str1 = str_name.toStdString();
video=VideoCapture(str1, CAP_FFMPEG, {CAP_PROP_HW_ACCELERATION, VIDEO_ACCELERATION_ANY});
video=VideoCapture(str1);
其中CamIP[0]是存储在数据库中摄像头的IP,不同摄像头有不同的、数据流,个人根据自己摄像头的视频流更改即可。
3.主线程发送信号,开始显示摄像头画面,子线程开始获取图像,转化
//这是主线程发送信号
emit sendCamDispay();
emit sendCamDispay2();
emit sendCamDispay3();
emit sendCamDispay4();
//这是子线程接受信号,读取转化图像
while(1)
{
if(video.isOpened())
{
video.read(src); //读取输入像素
if(!src.empty())
{
cvtColor(src,csrc,COLOR_BGR2RGB); //颜色空间转换
QImage img = QImage((const unsigned char*)csrc.data, // uchar* data
csrc.cols, csrc.rows, csrc.step, QImage::Format_RGB888);//格式转化
emit SendPic(img);
}
}
}
4.主线程显示图片
//这里是为了获取摄像头的帧率
uint ss = QDateTime::currentDateTime().toTime_t();
if(num_flag == 0)
{
num_start = ss;
num_flag = 1;
}
num_sum++;
if(ss - num_start == 2) //2s内的帧率
{
int num = num_sum /2;
ui->label_fps->setText(QString::number(num));
num_sum = 0;
num_flag = 0;
num_start = 0;
}
//摄像头显示
int a = ui->label_cam->width();
int b = ui->label_cam->height();
QImage ime = image.scaled(a,b); //自定义缩放
ui->label_cam->setPixmap(QPixmap::fromImage(ime));
ui->label_cam->show();
这样就完成了摄像头的实时监控。
三、摄像头的历史回放
同理摄像头回放程度也需要一个单独的线程,从文件夹读取到视频的路径,用VideoCapture读取视频,写入到Mat类的图片之中,然后将Mat图片转化成Qimage类,显示到主线程之中,话不多说,直接上代码。
void VideoScroll::getScrollPath(QString path)
{
camera = VideoCapture(path.toStdString());
timer_ID = this->startTimer(50); //数值越小,回放速度越快
}
void VideoScroll::timerEvent ( QTimerEvent * event)
{
if(event->timerId() == timer_ID)
{
VideoDisplay();
}
}
void VideoScroll::VideoDisplay()
{
camera >> inFrame;
if(!inFrame.empty())
{
cvtColor(inFrame, outFrame,COLOR_BGR2RGB); //颜色空间转换
if(!outFrame.empty())
{
emit SendPic(QPixmap::fromImage(
QImage(
outFrame.data,
outFrame.cols,
outFrame.rows,
outFrame.step,
QImage::Format_RGB888)));
}
}
}
到此,摄像头的实时监控和历史回放就完成了,其实还是很简单的,做为opencv的初学者,一起加油。
取之于互联网,还之于互联网, 瑞思拜~