开发者社区> gnuhpc> 正文

【OpenCV学习】安防监控可疑走动报警

简介: 作者:gnuhpc 出处:http://www.cnblogs.com/gnuhpc/ /* * ===================================================================================== * * Filename: motiondetect.
+关注继续查看

作者:gnuhpc
出处:http://www.cnblogs.com/gnuhpc/

/*
 * =====================================================================================
 *
 *       Filename:  motiondetect.c
 *
 *    Description:  A method of detecting the motion
 *
 *        Version:  1.0
 *        Created:  01/10/2009 03:32:21 PM
 *       Revision:  none
 *       Compiler:  gcc
 *
 *         Author:  Futuredaemon (BUPT), gnuhpc@gmail.com
 *        Company:  BUPT_UNITED
 *
 * =====================================================================================
 */
#include <stdio.h>
#include <time.h>
#include <cv.h>
#include <cxcore.h>
#include <highgui.h>
int main( int argc, char** argv )
{
//声明IplImage指针
  IplImage* pFrame = NULL;     //pFrame为视频截取的一帧
  IplImage* pFrame1 = NULL;      //第一帧
  IplImage* pFrame2 = NULL;//第二帧
  IplImage* pFrame3 = NULL;//第三帧
  IplImage* pFrImg = NULL;     //pFrImg为当前帧的灰度图
  IplImage* pBkImg = NULL;     //pBkImg为当前背景的灰度图
  IplImage* pBkImgTran = NULL;//pBkImgTran为当前背景处理过的图像
  IplImage* pFrImgTran = NULL;//pFrImgTran为当前背景处理过的图像
  CvMat* pFrameMat = NULL;     //pFrameMat为当前灰度矩阵
  CvMat* pFrMat = NULL;      //pFrMat为当前前景图矩阵,当前帧减去背景图
  CvMat* bg1 = NULL;
  CvMat* bg2 = NULL;
  CvMat* bg3 = NULL;
  CvMat* pFrMatB = NULL;     //pFrMatB为二值化(0,1)的前景图
  CvMat* pBkMat = NULL;
  CvMat* pZeroMat = NULL;               //用于计算bg1 - bg2 的值
  CvMat* pZeroMatB = NULL;//用于计算 pZeroMat阈值化后来判断有多少个零的临时矩阵
  CvCapture* pCapture = NULL;
  int warningNum = 0;      //检测到有异物入侵的次数
  int nFrmNum = 0;//帧计数
  int status = 0;        //状态标志位
//创建窗口
  cvNamedWindow("video", 1);
  cvNamedWindow("background",1);//背景
  cvNamedWindow("foreground",1);//前景
//使窗口有序排列
  cvMoveWindow("video", 30, 0);
  cvMoveWindow("background", 360, 0);
  cvMoveWindow("foreground", 690, 0);
  if ( argc > 2 )
    {
      fprintf(stderr, "Usage: bkgrd [video_file_name]/n");
      return -1;
    }
//打开摄像头
  if (argc ==1)
    if ( !(pCapture = cvCaptureFromCAM(-1)))
      {
        fprintf(stderr, "Can not open camera./n");
        return -2;
      }
//打开视频文件
  if (argc == 2)
    if ( !(pCapture = cvCaptureFromFile(argv[1])))
      {
        fprintf(stderr, "Can not open video file %s/n", argv[1]);
        return -2;
      }
//开始计时
  time_t start,end;
  time(&start);        //time() 返回从1970年1月1号00:00:00开始以来到现在的秒数(有10为数字)。
  printf("%d/n",start);
//逐帧读取视频
  while (pFrame = cvQueryFrame( pCapture ))
    {
      nFrmNum++;
      //如果是第一帧,需要申请内存,并初始化
      if (nFrmNum == 1)
        {
          pBkImg = cvCreateImage(cvSize(pFrame->width, pFrame->height), IPL_DEPTH_8U,1);
          pFrImg = cvCreateImage(cvSize(pFrame->width, pFrame->height), IPL_DEPTH_8U,1);
          pBkImgTran = cvCreateImage(cvSize(pFrame->width,pFrame->height), IPL_DEPTH_8U,1);
          pFrImgTran = cvCreateImage(cvSize(pFrame->width,pFrame->height), IPL_DEPTH_8U,1);
          pBkMat = cvCreateMat(pFrame->height, pFrame->width, CV_32FC1);
          pZeroMat = cvCreateMat(pFrame->height, pFrame->width, CV_32FC1);
          pFrMat = cvCreateMat(pFrame->height, pFrame->width, CV_32FC1);
          pFrMatB = cvCreateMat(pFrame->height, pFrame->width, CV_8UC1);
          pZeroMatB = cvCreateMat(pFrame->height, pFrame->width, CV_8UC1);
          pFrameMat = cvCreateMat(pFrame->height, pFrame->width, CV_32FC1);
          cvZero(pZeroMat);
          //转化成单通道图像再处理
          cvCvtColor(pFrame, pBkImg, CV_BGR2GRAY);
          //转换为矩阵
          cvConvert(pFrImg, pBkMat);
        }
      else /* 不是第一帧的就这样处理 */
        {
          //pFrImg为当前帧的灰度图
          cvCvtColor(pFrame, pFrImg, CV_BGR2GRAY);
          //pFrameMat为当前灰度矩阵
          cvConvert(pFrImg, pFrameMat);
          //pFrMat为前景图矩阵,当前帧减去背景图
          cvAbsDiff(pFrameMat, pBkMat, pFrMat);
          //pFrMatB为二值化(0,1)的前景图
          cvThreshold(pFrMat,pFrMatB, 60, 1, CV_THRESH_BINARY);
          //将图像矩阵转化为图像格式,用以显示
          cvConvert(pBkMat, pBkImgTran);   
          cvConvert(pFrMat, pFrImgTran);   
          //显示图像
          cvShowImage("video", pFrame);
          cvShowImage("background", pBkImgTran); //显示背景
          cvShowImage("foreground", pFrImgTran); //显示前景
          //以上是每抓取一帧都要做的工作,下面进行危险检测
          if (cvCountNonZero(pFrMatB) > 10000 && status == 0) //表示是第一帧的异物大于1W个像数点
            {/* 则需要将当前帧存储为第一帧 */
              pFrame1 = cvCloneImage(pFrame);
              bg1 = cvCloneMat(pFrMat);
              status = 1;      //继续采集第2帧
            }
          else if (cvCountNonZero(pFrMatB) < 10000 && status == 1) // 表示第一帧的异物大于1W个像数点,而第二帧没有,则报警
            {
              printf("NO.%d warning!!!!/n/n",warningNum++);
              status = 0;
            }
          else if (cvCountNonZero(pFrMatB) > 10000 && status == 1)// 表示第一帧和第二帧的异物都大于1W个像数点
            {
              pFrame2 = cvCloneImage(pFrame);
              bg2 = cvCloneMat(pFrMat);
              cvAbsDiff(bg1, bg2, pZeroMat);
              cvThreshold(pZeroMat,pZeroMatB, 20, 1, CV_THRESH_BINARY);
              if (cvCountNonZero(pZeroMatB) > 3000 ) //表示他们不连续,这样的话要报警
                {
                  printf("NO.%d warning!!!!/n/n",warningNum++);
                  status = 0;
                }
              else
                {
                  status = 2;                   //继续采集第3帧
                }
            }
          else if (cvCountNonZero(pFrMatB) < 10000 && status == 2)//表示第一帧和第二帧的异物都大于1W个像数点,而第三帧没有
            {
              //报警
              printf("NO.%d warning!!!!/n/n",warningNum++);
              status = 0;
            }
          else if (cvCountNonZero(pFrMatB) > 10000 && status == 2)//表示连续3帧的异物都大于1W个像数点
            {
              pFrame3 = cvCloneImage(pFrame);
              bg3 = cvCloneMat(pFrMat);
              cvAbsDiff(bg2, bg3, pZeroMat);
              cvThreshold(pZeroMat,pZeroMatB, 20, 1, CV_THRESH_BINARY);
              if (cvCountNonZero(pZeroMatB) > 3000 ) //表示他们不连续,这样的话要报警
                {
                  printf("NO.%d warning!!!!/n/n",warningNum++);
                }
              else //表示bg2,bg3连续
                {
                  cvReleaseMat(&pBkMat);
                  pBkMat = cvCloneMat(pFrameMat); //更新背景
                }
                status = 0;                //进入下一次采集过程
            }
          //如果有按键事件,则跳出循环
          //此等待也为cvShowImage函数提供时间完成显示
          //等待时间可以根据CPU速度调整
          if ( cvWaitKey(2) >= 0 )
            break;
        }/* The End of the else */
    }/* The End of th while */
//销毁窗口
    cvDestroyWindow("video");
    cvDestroyWindow("background");
    cvDestroyWindow("foreground");
//释放图像和矩阵
    cvReleaseImage(&pFrImg);
    cvReleaseImage(&pBkImg);
    cvReleaseMat(&pFrameMat);
    cvReleaseMat(&pFrMat);
    cvReleaseMat(&pBkMat);
    cvReleaseCapture(&pCapture);
  return 0;
}

所研究的运动检测和背景更新方法实现的步骤如下:
(1)开辟静态内存,对图像进行初始化准备采集;
(2)采集图像,定义参数k,作为图像序列计数。采集第1幅图像时,则根据第一帧的大小信息进行矩阵、图像的初始化,并且将第一帧图像进行灰度化处理,并转化为矩阵,作为背景图像及矩阵;如果k不等于1则把当前帧进行灰度化处理,并转化为矩阵,作为当前帧的图像及矩阵。用当前帧的图像矩阵和背景帧的图像矩阵做差算出前景图矩阵并对其进行二值化以便计算它与背景帧差别较大的像素个数,也就是二值化后零的个数。
当第一帧的异物大于1W个像数点则需要将当前帧存储为第一帧,并且将系统的状态转为1——采集第二帧;
第一帧和第二帧的异物都大于1W个像数点时,将当前帧存储为第二帧,通过判断第一帧和第二帧的差值来确定两帧是否连续,若连续则将系统状态转为2——采集第三帧,若不连续则报警,并把系统状态转为0——采集背景帧;
当第一帧和第二帧的异物都大于1W个像数点,而第三帧没有时则报警;
若连续3帧的异物都大于1W个像数点时,将当前帧存储为第三帧,通过判断第二帧和第三帧的差值来确定两帧是否连续,若连续则将更新背景,若不连续则报警。然后把系统状态转为0——采集背景帧。
注意其中有一个0-1-2-0....的状态机。

 

作者:gnuhpc
出处:http://www.cnblogs.com/gnuhpc/


               作者:gnuhpc
               出处:http://www.cnblogs.com/gnuhpc/
               除非另有声明,本网站采用知识共享“署名 2.5 中国大陆”许可协议授权。


分享到:

版权声明:本文内容由阿里云实名注册用户自发贡献,版权归原作者所有,阿里云开发者社区不拥有其著作权,亦不承担相应法律责任。具体规则请查看《阿里云开发者社区用户服务协议》和《阿里云开发者社区知识产权保护指引》。如果您发现本社区中有涉嫌抄袭的内容,填写侵权投诉表单进行举报,一经查实,本社区将立刻删除涉嫌侵权内容。

相关文章
阿里云ECS云服务器初始化设置教程方法
阿里云ECS云服务器初始化是指将云服务器系统恢复到最初状态的过程,阿里云的服务器初始化是通过更换系统盘来实现的,是免费的,阿里云百科网分享服务器初始化教程: 服务器初始化教程方法 本文的服务器初始化是指将ECS云服务器系统恢复到最初状态,服务器中的数据也会被清空,所以初始化之前一定要先备份好。
14282 0
运维监控系统建设 | 学习笔记
快速学习运维监控系统建设,进行运维监控系统的配置。
155 0
阿里云服务器如何登录?阿里云服务器的三种登录方法
购买阿里云ECS云服务器后如何登录?场景不同,阿里云优惠总结大概有三种登录方式: 登录到ECS云服务器控制台 在ECS云服务器控制台用户可以更改密码、更换系.
29209 0
【OpenCV学习】安防监控可疑走动报警
作者:gnuhpc 出处:http://www.cnblogs.com/gnuhpc/ /* * ===================================================================================== * * Filename: motiondetect.
744 0
阿里云服务器端口号设置
阿里云服务器初级使用者可能面临的问题之一. 使用tomcat或者其他服务器软件设置端口号后,比如 一些不是默认的, mysql的 3306, mssql的1433,有时候打不开网页, 原因是没有在ecs安全组去设置这个端口号. 解决: 点击ecs下网络和安全下的安全组 在弹出的安全组中,如果没有就新建安全组,然后点击配置规则 最后如上图点击添加...或快速创建.   have fun!  将编程看作是一门艺术,而不单单是个技术。
20723 0
阿里云服务器怎么设置密码?怎么停机?怎么重启服务器?
如果在创建实例时没有设置密码,或者密码丢失,您可以在控制台上重新设置实例的登录密码。本文仅描述如何在 ECS 管理控制台上修改实例登录密码。
23589 0
Nginx 状态监控、缓存的两种机制(学习笔记十四)
这里 Cache 有两种情况说明,一种是浏览器访问Nginx,浏览器会Cache;一种是Nginx 访问后端,Nginx 自己Cache 。
1102 0
数据库的备份恢复与监控|学习笔记
快速学习数据库的备份恢复与监控
39 0
+关注
406
文章
0
问答
文章排行榜
最热
最新
相关电子书
更多
JS零基础入门教程(上册)
立即下载
性能优化方法论
立即下载
手把手学习日志服务SLS,云启实验室实战指南
立即下载