本文最后更新于2020年12月8日,已超过 6 个月没更新!

数字视频技术及应用实验三:运动目标检测

实验内容及要求

阅读实验三指导书,任选一种方法(背景减法、帧差法等)编程实现视频中运动目标检测,并分析实验结果。

实验内容指导

1.在vs中新建工程;
2.配置OpenCV;
3.定义读取视频的变量
4.定义相应的指针和结构并初始化
5.将视频灰度化,并将指针的内容存到相应的结构体中
6.计算视频中前后两帧的差值,并将其二值化;
7.更新背景,并在二值图像中检索轮廓
8.在原视频中框出运动物体
9.在视频中显示最终结果

实验代码实现

#include <iostream>  
#include "opencv2/opencv.hpp"  

using namespace cv;
using namespace std;

Mat MoveDetect(Mat temp, Mat frame)   //运动物体检测
{
    Mat result = frame.clone();
    Mat gray1, gray2;
    cvtColor(temp, gray1, CV_BGR2GRAY);
    cvtColor(frame, gray2, CV_BGR2GRAY);    // 将background和frame转为灰度图  
    Mat diff;
    absdiff(gray1, gray2, diff);    // 将background和frame做差  
    imshow("diff", diff);
    Mat diff_thresh;
    threshold(diff, diff_thresh, 50, 255, CV_THRESH_BINARY);    // 对差值图diff_thresh进行阈值化处理  
    imshow("diff_thresh", diff_thresh);
    Mat kernel_erode = getStructuringElement(MORPH_RECT, Size(3, 3));
    Mat kernel_dilate = getStructuringElement(MORPH_RECT, Size(18, 18));
    erode(diff_thresh, diff_thresh, kernel_erode);          // 腐蚀  
    imshow("erode", diff_thresh);
    dilate(diff_thresh, diff_thresh, kernel_dilate);            // 膨胀  
    imshow("dilate", diff_thresh);
    vector<vector<Point>> contours;
    findContours(diff_thresh, contours, CV_RETR_EXTERNAL, CV_CHAIN_APPROX_NONE);    // 查找轮廓并绘制轮廓  
    //drawContours(result, contours, -1, Scalar(0, 0, 255), 2);     // 在result上绘制轮廓
    vector<Rect> boundRect(contours.size());
    for (int i = 0; i < contours.size(); i++)       // 查找正外接矩形  
    {
        boundRect[i] = boundingRect(contours[i]);
        rectangle(result, boundRect[i], Scalar(0, 255, 0), 2);          // 在result上绘制正外接矩形
    }
    return result;
}

int main()
{
    VideoCapture video("exp3.avi");
    if (!video.isOpened())
    {
        cout << "video open error!" << endl;
        return 0;
    }
    int frameCount = video.get(CV_CAP_PROP_FRAME_COUNT);    // 获取帧数
    double FPS = video.get(CV_CAP_PROP_FPS);    // 获取FPS
    Mat frame;
    Mat temp;           // 存储前一帧图像
    Mat result;         // 存储结果图像
    for (int i = 0; i < frameCount; i++)
    {
        video >> frame;
        imshow("frame", frame);
        if (frame.empty())
        {
            cout << "frame is empty!" << endl;
            break;
        }
        int framePosition = video.get(CV_CAP_PROP_POS_FRAMES);          // 获取帧位置
        cout << "framePosition: " << framePosition << endl;             //输出帧位置
        if (i == 0)         // 如果为第一帧(temp还为空)
        {
            result = MoveDetect(frame, frame);          // 调用MoveDetect()进行运动物体检测,返回值存入result
        }
        else        //若不是第一帧(temp有值了)
        {
            result = MoveDetect(temp, frame);               // 调用MoveDetect()进行运动物体检测,返回值存入result
        }
        imshow("result", result);
        if (waitKey(1000.0 / FPS) == 27)
        {
            cout << "ESC退出!" << endl;
            break;
        }
        temp = frame.clone();
    }
    return 0;
}

疏影横斜水清浅,暗香浮动月黄昏