运动目标检测与跟踪

发布时间 2023-10-16 07:25:47作者: blackstrom

091701

#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include <QMainWindow>
#include <QTimer>
#include <QImage>
#include "opencv2/opencv.hpp"
using namespace cv;

using namespace std;//这段代码是C++中的一条命名空间的声明语句,即使用std命名空间的声明。命名空间可以用来组织和管理代码中的标识符(如变量、函数、类等),避免命名冲突,并使代码更清晰可读。
namespace Ui {
class MainWindow;
}

class MainWindow : public QMainWindow
{
Q_OBJECT

public:
explicit MainWindow(QWidget *parent = 0);
~MainWindow();

private slots:
void on_btnPlay_clicked();

void on_btnStop_clicked();
void importFrame();

private:
Ui::MainWindow *ui;
VideoCapture capture;
QTimer *timer;
Mat frame;
Ptr<BackgroundSubtractorMOG2>ptrMOG;
};

#endif // MAINWINDOW_H

 

 

 

 

 

 

#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <QDebug>

MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
this->setWindowTitle("video play with Qt Opencv");

ptrMOG=createBackgroundSubtractorMOG2(500,16,false);

timer=new QTimer(this);
connect(timer,SIGNAL(timeout()),this,SLOT(importFrame()));

}

MainWindow::~MainWindow()
{
delete ui;
}

void MainWindow::on_btnPlay_clicked()
{
capture.open("F:/0.avi");

double rate=capture.get(CAP_PROP_FPS);
double timerDelay=1000/rate;
timer->start(timerDelay);

 

}

void MainWindow::on_btnStop_clicked()
{
timer->stop();
capture.release();
// capture=0;
qDebug()<<"stop";

}

void MainWindow::importFrame()
{
Mat currentFrame;
Mat grayFrame,foreGround;

 

 

capture>>currentFrame;
//capture>>frame;
if(!currentFrame.empty())
//if(!frame.empty())
{

qDebug()<<"video is running";
// cvtColor(currentFrame,grayFrame,COLOR_BGR2RGB);
cvtColor(currentFrame,grayFrame,COLOR_BGR2GRAY);

Mat result=currentFrame.clone();

ptrMOG->apply(grayFrame,foreGround,0.05);

threshold(foreGround,foreGround,25,255,THRESH_BINARY);//这段代码使用OpenCV中的threshold函数对前景图像foreGround进行阈值处理。threshold函数可以将图像转换为二值图像,根据设定的阈值将像素值分为两类:小于等于阈值的像素设为0,大于阈值的像素设为给定的最大值(这里是255)。具体来说,参数解释如下:第一个参数是输入的前景图像,第二个参数是输出的二值图像,第三个参数是设定的阈值(这里是25),第四个参数是最大值(这里是255),THRESH_BINARY表示使用二进制阈值处理方法。调用这个函数后,前景图像中小于等于25的像素值将被设为0,大于25的像素值将被设为255,以得到一个二值化的前景图像。
//erode图像腐蚀操作
Mat kernelErode=getStructuringElement(MORPH_RECT,Size(5,5));//这段代码使用OpenCV中的getStructuringElement函数创建了一个称为kernelErode的结构元素(structuring element)。结构元素是用于形态学操作(如腐蚀、膨胀等)的一种模板。getStructuringElement函数的第一个参数是指定结构元素的形状,这里是MORPH_RECT,表示矩形形状。第二个参数是指定结构元素的大小,这里是Size(5, 5),表示宽度和高度都是5个像素。调用这个函数后,将会得到一个5x5的矩形结构元素,可用于后续的形态学操作,比如腐蚀操作。
erode(foreGround,foreGround,kernelErode);//这段代码使用OpenCV中的erode函数对前景图像foreGround进行腐蚀操作。腐蚀是形态学操作中的一种,它可以缩小图像中前景物体的区域。erode函数的第一个参数是输入的前景图像,第二个参数是输出的腐蚀后的图像,第三个参数是腐蚀操作使用的结构元素(这里是kernelErode)。调用这个函数后,图像中的前景物体会被缩小,边界周围的像素值会向内部蔓延,因此前景物体的轮廓会被腐蚀掉一部分。这样可以去除一些噪点或细小的前景物体,得到更清晰的前景图像。

//dilate图像膨胀
Mat kernelDilate=getStructuringElement(MORPH_RECT,Size(11,11));
dilate(foreGround,foreGround,kernelDilate);

//框选运动目标
vector<vector<Point>>contours;//vector<vector<Point>> contours; 声明了一个名为contours的变量,它可以存储多个轮廓(contour)。每个轮廓是一个由多个Point对象构成的一维向量,而所有的轮廓又被存储在二维向量contours中。
findContours(foreGround,contours,RETR_EXTERNAL,CHAIN_APPROX_NONE);//查找前景图像foreGround中的轮廓,并将它们存储在contours变量中。findContours函数的第一个参数是输入的前景图像,第二个参数是输出的存储轮廓的变量(这里是contours),第三个参数是轮廓检索模式(RETR_EXTERNAL),第四个参数是轮廓近似方法(CHAIN_APPROX_NONE)。轮廓检索模式RETR_EXTERNAL表示只检测最外层的轮廓,即不包括轮廓内部的子轮廓。轮廓近似方法CHAIN_APPROX_NONE表示将轮廓的所有点都存储起来,而不进行轮廓的简化。


for(int i=0;i<contours.size();i++)//在每次循环中,会执行循环体内的代码块。循环体内的代码可以对每个轮廓进行操作,例如获取轮廓的属性、绘制轮廓、计算轮廓的面积等。通过使用循环变量i作为索引,在每次循环中可以访问contours中的不同轮廓。
{
rectangle(result,boundingRect(contours[i]),Scalar(0,255,0),1);//rectangle函数的第一个参数是绘制矩形的图像,这里是result。第二个参数是矩形的位置和大小,通过boundingRect函数得到。第三个参数是矩形的颜色,这里是Scalar(0, 255, 0),表示绿色。第四个参数是绘制线条的粗细,这里是1,表示线条宽度为1个像素。
}

//cvtColor(result,result,COLOR_BGR2RGB);

//cvtColor(frame,frame,COLOR_BGR2RGB);
QImage showVideo=QImage((const unsigned char*)(result.data),result.cols,result.rows,result.step,QImage::Format_RGB888);
//QImage showVideo=QImage((const unsigned char*)(result.data),result.cols,result.rows,result.step,QImage::Format_Indexed8);
//QImage showVideo=QImage((const unsigned char*)(frame.data),frame.cols,frame.rows,frame.step,QImage::Format_RGB888);
ui->labelVideo->setPixmap(QPixmap::fromImage(showVideo.scaled(ui->labelVideo->size(),Qt::KeepAspectRatio,Qt::SmoothTransformation)));
}
else
{
qDebug()<<"play is over";
timer->stop();
}
}