当前位置:   article > 正文

opencv动态目标检测_opencv c++ 移动目标侦测

opencv c++ 移动目标侦测


前言

很久没更新文章了,这次因为工作场景需要检测动态目标,特此记录一下。


一、效果展示

在这里插入图片描述

二、实现方法

基于OpenCV库的背景减除方法实现的视频中的移动目标检测示例。通过从输入视频中提取前景目标,然后在特定区域内绘制检测到的移动物体的边界框。主要函数方法如下:

构造形态学操作所需的核:

cv2.getStructuringElement: 创建形态学操作所需的结构元素,这里使用椭圆形的结构元素。

创建背景减除模型:

cv2.createBackgroundSubtractorMOG2(): 创建一个高斯混合模型背景减除器,用于提取视频中的前景。

形态学操作:

cv2.morphologyEx(fgmk, cv2.MORPH_OPEN, kernel): 对前景图像进行形态学开运算,用于去除噪声并平滑前景目标。

轮廓检测:

cv2.findContours(fgmk.copy(), cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE): 寻找前景图像中的轮廓。

三、代码

需要根据自己的视频适当微调参数

python代码

import cv2
import numpy as np

def main(path):
    # 第一步:使用cv2.VideoCapture读取视频
    camera = cv2.VideoCapture(path)

    width = int(camera.get(cv2.CAP_PROP_FRAME_WIDTH))
    height = int(camera.get(cv2.CAP_PROP_FRAME_HEIGHT))

    per_width = int(width / 4)
    per_height = int(height / 2)

    # 第二步:cv2.getStructuringElement构造形态学使用的kernel
    kernel = cv2.getStructuringElement(cv2.MORPH_ELLIPSE, (3, 3))
    # 第三步:构造高斯混合模型
    model = cv2.createBackgroundSubtractorMOG2()
    # model = cv2.createBackgroundSubtractorKNN()

    # 设定区域,后面可以用于判断是否在区域内(可以设置为多边形)
    contour = np.array([[0, 0], [3 * per_width, per_height], [3 * per_width, height], [0, height]])

    while True:
        # 第四步:读取视频中的图片,并使用高斯模型进行拟合
        ret, frame = camera.read()
        # 运用高斯模型进行拟合,在两个标准差内设置为0,在两个标准差外设置为255
        fgmk = model.apply(frame)
        # 第五步:使用形态学的开运算做背景的去除
        fgmk = cv2.morphologyEx(fgmk, cv2.MORPH_OPEN, kernel)
        # 第六步:cv2.findContours计算fgmk的轮廓
        contours, hierarchy = cv2.findContours(fgmk.copy(), cv2.RETR_EXTERNAL,
                                               cv2.CHAIN_APPROX_SIMPLE)  # 该函数计算一幅图像中目标的轮廓

        for c in contours:
            # 过滤面积较小的扰动
            if cv2.contourArea(c) < 80:
                continue

            else:
                x, y, w, h = cv2.boundingRect(c)  # 该函数计算矩形的边界框
                center = (int(x + w / 2), int(y + h / 2))

                # 判断点是否在多边形区域内
                result = cv2.pointPolygonTest(contour, center, False)

                if result > 0:
                    cv2.rectangle(frame, (x, y), (x + w, y + h), (0, 0, 255), 2)

        # 第八步:进行图片的展示
        cv2.imshow('fgmk', fgmk)
        cv2.imshow('frame', frame)

        if cv2.waitKey(1) & 0xff == 27:
            break

    camera.release()
    cv2.destroyAllWindows()


if __name__ == '__main__':
    path = "./video/test.mp4"
    main(path)
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62

C++代码

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

using namespace std;
using namespace cv;

int main(int argc, char** argv) {
    string path = "../test2.mp4";
    // 第一步:使用VideoCapture读取视频
    VideoCapture camera(path);

    int width = static_cast<int>(camera.get(CAP_PROP_FRAME_WIDTH));
    int height = static_cast<int>(camera.get(CAP_PROP_FRAME_HEIGHT));

    int per_width = width / 4;
    int per_height = height / 2;

    // 第二步:getStructuringElement构造形态学使用的kernel
    Mat kernel = getStructuringElement(MORPH_ELLIPSE, Size(3, 3));
    // 第三步:构造高斯混合模型
    Ptr<BackgroundSubtractorMOG2> model = createBackgroundSubtractorMOG2();
    // Ptr<BackgroundSubtractorKNN> model = createBackgroundSubtractorKNN();

    // 设定区域,后面可以用于判断是否在区域内(可以设置为多边形)
    vector<Point> contour = {Point(0, 0), Point(3 * per_width, per_height), Point(3 * per_width, height), Point(0, height)};

    while (true) {
        // 第四步:读取视频中的图片,并使用高斯模型进行拟合
        Mat frame;
        bool ret = camera.read(frame);
        if (!ret) break;

        // 运用高斯模型进行拟合,在两个标准差内设置为0,在两个标准差外设置为255
        Mat fgmk;
        model->apply(frame, fgmk);
        // 第五步:使用形态学的开运算做背景的去除
        morphologyEx(fgmk, fgmk, MORPH_OPEN, kernel);
        // 第六步:findContours计算fgmk的轮廓
        vector<vector<Point>> contours;
        vector<Vec4i> hierarchy;
        findContours(fgmk.clone(), contours, hierarchy, RETR_EXTERNAL, CHAIN_APPROX_SIMPLE);

        for (const auto& c : contours) {
            if (contourArea(c) < 80)
                continue;
            else {
                Rect rect = boundingRect(c);
                Point center(rect.x + rect.width / 2, rect.y + rect.height / 2);

                // 判断点是否在多边形区域内
                double result = pointPolygonTest(contour, center, false);

                if (result > 0)
                    rectangle(frame, rect, Scalar(0, 0, 255), 2);
            }
        }

        // 第八步:进行图片的展示
        imshow("fgmk", fgmk);
        imshow("frame", frame);

        if (waitKey(1) == 27) // 按下ESC键退出
            break;
    }

    camera.release();
    destroyAllWindows();

    return 0;
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70

总结

这段代码演示了背景减除方法在移动目标检测中的应用,通过检测前景目标并在特定区域内绘制边界框,可以用于一些简单的运动分析和目标跟踪应用。

参考文档

https://blog.csdn.net/Gavinmiaoc/article/details/96474368
https://blog.csdn.net/drippingstone/article/details/116186462
如果阅读本文对你有用,欢迎一键三连呀!!!
2023年8月9日17:15:40
在这里插入图片描述

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/盐析白兔/article/detail/391081
推荐阅读
相关标签
  

闽ICP备14008679号