基于opencv的BackgroundSubtractorMOG2目标追踪

举报
风吹稻花香 发表于 2021/06/04 23:53:19 2021/06/04
【摘要】 基于opencv的BackgroundSubtractorMOG2目标追踪 BackgroundSubtractorMOG2是以高斯混合模型为基础的背景/前景分割算法。它是以2004年和2006年Z.Zivkovic的两篇文章为基础的。这个算法的一个特点是它为每一个像素选择一个合适数目的高斯分布。(上一个方法中我们使用是K高斯分布)。这样就会对由于亮度等发生变...


基于opencv的BackgroundSubtractorMOG2目标追踪

BackgroundSubtractorMOG2是以高斯混合模型为基础的背景/前景分割算法。它是以2004年和2006年Z.Zivkovic的两篇文章为基础的。这个算法的一个特点是它为每一个像素选择一个合适数目的高斯分布。(上一个方法中我们使用是K高斯分布)。这样就会对由于亮度等发生变化引起的场景变化产生更好的适应。和前面一样我们需要创建一个背景对象。但在这里我们我们可以选择是否检测阴影。如果detectShadows = True(默认值),它就会检测并将影子标记出来,但是这样做会降低处理速度。影子会被标记为灰色。

这里我们采用opencv实现视频追踪,对于opencv的安装、配置和使用,网上有很多教程,我们这里就不在说明。如果你对opencv不太了解,请自行查资料学习。话归正题,这里我将会分别从Python和c++实现BackgroundSubtractorMOG2,我使用的是opencv3.1linux版本。
Python代码:


        import numpy as np
        import cv2
        import time
        import datetime
        cap = cv2.VideoCapture(0)
        kernel = cv2.getStructuringElement(cv2.MORPH_ELLIPSE,(3,3))
        fgbg = cv2.createBackgroundSubtractorMOG2()
        fourcc = cv2.VideoWriter_fourcc(*'XVID')
        frame1 = np.zeros((640,480))
        out = cv2.VideoWriter(datetime.datetime.now().strftime("%A_%d_%B_%Y_%I_%M_%S%p")+'.avi',fourcc, 5.0, np.shape(frame1))
        while(1):
         ret, frame = cap.read()
         fgmask = fgbg.apply(frame)
         (_,cnts, _) = cv2.findContours(fgmask.copy(), cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
         maxArea = 0
        for c in cnts:
         Area = cv2.contourArea(c)
        if Area < maxArea :
         #if cv2.contourArea(c) < 500:
         (x, y, w, h) = (0,0,0,0)
        continue
        else:
        if Area < 1000:
         (x, y, w, h) = (0,0,0,0)
        continue
        else:
         maxArea = Area
         m=c
         (x, y, w, h) = cv2.boundingRect(m)
         cv2.rectangle(frame, (x, y), (x + w, y + h), (0, 255, 0), 2)
         out.write(frame)
         cv2.imshow('frame',frame)
         k = cv2.waitKey(30)&0xff
        if k==27:
        break
        out.release()
        cap.release()
        cv2.destoryAllWindows()
     
   
   
   

c++版本:
VideoDetect.h


        #pragma once
        #include <opencv2/opencv.hpp>
        #include <opencv2/highgui.hpp>
        using namespace std;
        using namespace cv;
        enum VIDEOTYPE
        {
         CAMERAVIDEO/*摄像头*/,FILEVIDEO/*视频*/
        };
        class MOG2Detector
        {
        public:
         MOG2Detector();
         ~MOG2Detector();
        /*
         VIDEOTYPE 指定摄像头或者文件
         path 文件路径
         WindowName opencv可视化窗口名称
         */
         MOG2Detector(VIDEOTYPE type,char * path = "E:/image/s.avi",char * WindowName = "Video");
        //开始
        void startDecect();
        private:
        char * WinName;
         VIDEOTYPE VideoType;
         cv::VideoCapture capture;
         cv::Ptr<cv::BackgroundSubtractorMOG2> fgbg;
        };
     
   
   
   

VideoDetect.cpp:


        #include "stdafx.h"
        #include "MOG2Detector.h"
        MOG2Detector::MOG2Detector()
        {
        }
        MOG2Detector::~MOG2Detector()
        {
        }
        MOG2Detector::MOG2Detector(VIDEOTYPE type, char * path, char * WindowName)
        {
        if (type == CAMERAVIDEO)
         {
         capture.open(0);
         }
        else if (type == FILEVIDEO)
         {
         capture.open("E:/image/s.avi");
         }
        else
         {
        cout << "Type is error, you can input CAMERAVIDEO or FILEVIDEO" << endl;
        return;
         }
        if (!capture.isOpened())
         {
        std::cout << "video camera capture open fail! \n" << std::endl;
        exit(1);
         }
         fgbg = cv::createBackgroundSubtractorMOG2();
         WinName = WindowName;
        }
        void MOG2Detector::startDecect()
        {
         cv::Mat frame, fgmask;
        //cnts存储边缘信息
        std::vector<std::vector<cv::Point> > cnts;
         cv::namedWindow("video", 1);
        while (1)
         {
         capture.read(frame);
         fgbg->apply(frame, fgmask);
        //检测每一帧边缘
         findContours(fgmask, cnts, RETR_EXTERNAL, CHAIN_APPROX_SIMPLE);
        float Area;
         Rect rect;
        vector<Point> m;
        for (int i = cnts.size() - 1; i >= 0; i--)
         {
        vector<Point> c = cnts[i];
        //获取面积
         Area = contourArea(c);
        if (Area < 50)//50这个值根据需求设定,这里指的是目标的大小
         {
        continue;
         }
        else
         {
         m = c;
         }
         rect = boundingRect(m);
         rectangle(frame, rect, Scalar(0, 255, 0), 2);
         }
         resize(frame, frame, Size(480, 320));
         imshow("video", frame);
        char c = waitKey(33);
        if (c == 27)
        break;
         }
        //释放资源
         capture.release();
         cv::destroyWindow("video");
        }
     
   
   
   

最近比较忙,等到有时间在完善这些代码,添加注释!
实验结果
实验结果

文章来源: blog.csdn.net,作者:网奇,版权归原作者所有,如需转载,请联系作者。

原文链接:blog.csdn.net/jacke121/article/details/78365682

【版权声明】本文为华为云社区用户转载文章,如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。