OpenCV(12)安防监控可疑走动报警 cvCopy()和cvCloneImage()的区别

2024-02-03 11:38

本文主要是介绍OpenCV(12)安防监控可疑走动报警 cvCopy()和cvCloneImage()的区别,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

#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....的状态机。

cvCopy的原型是:
void cvCopy( const CvArr* src, CvArr* dst, const CvArr* mask=NULL );
在使用这个函数之前,你必须用cvCreateImage()一类的函数先开一段内存,然后传递给dst。cvCopy会把src中的数据复制到dst的内存中。

cvCloneImage的原型是:
IplImage* cvCloneImage( const IplImage* image );
在使用函数之前,不用开辟内存。该函数会自己开一段内存,然后复制好image里面的数据,然后把这段内存中的数据返回给你。

clone是把所有的都复制过来,也就是说不论你是否设置Roi,Coi等影响copy的参数,clone都会原封不动的克隆过来。
copy就不一样,只会复制ROI区域等。

这篇关于OpenCV(12)安防监控可疑走动报警 cvCopy()和cvCloneImage()的区别的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/674043

相关文章

Springboot @Autowired和@Resource的区别解析

《Springboot@Autowired和@Resource的区别解析》@Resource是JDK提供的注解,只是Spring在实现上提供了这个注解的功能支持,本文给大家介绍Springboot@... 目录【一】定义【1】@Autowired【2】@Resource【二】区别【1】包含的属性不同【2】@

Java中的String.valueOf()和toString()方法区别小结

《Java中的String.valueOf()和toString()方法区别小结》字符串操作是开发者日常编程任务中不可或缺的一部分,转换为字符串是一种常见需求,其中最常见的就是String.value... 目录String.valueOf()方法方法定义方法实现使用示例使用场景toString()方法方法

opencv图像处理之指纹验证的实现

《opencv图像处理之指纹验证的实现》本文主要介绍了opencv图像处理之指纹验证的实现,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学... 目录一、简介二、具体案例实现1. 图像显示函数2. 指纹验证函数3. 主函数4、运行结果三、总结一、

分辨率三兄弟LPI、DPI 和 PPI有什么区别? 搞清分辨率的那些事儿

《分辨率三兄弟LPI、DPI和PPI有什么区别?搞清分辨率的那些事儿》分辨率这个东西,真的是让人又爱又恨,为了搞清楚它,我可是翻阅了不少资料,最后发现“小7的背包”的解释最让我茅塞顿开,于是,我... 在谈到分辨率时,我们经常会遇到三个相似的缩写:PPI、DPI 和 LPI。虽然它们看起来差不多,但实际应用

python+opencv处理颜色之将目标颜色转换实例代码

《python+opencv处理颜色之将目标颜色转换实例代码》OpenCV是一个的跨平台计算机视觉库,可以运行在Linux、Windows和MacOS操作系统上,:本文主要介绍python+ope... 目录下面是代码+ 效果 + 解释转HSV: 关于颜色总是要转HSV的掩膜再标注总结 目标:将红色的部分滤

GORM中Model和Table的区别及使用

《GORM中Model和Table的区别及使用》Model和Table是两种与数据库表交互的核心方法,但它们的用途和行为存在著差异,本文主要介绍了GORM中Model和Table的区别及使用,具有一... 目录1. Model 的作用与特点1.1 核心用途1.2 行为特点1.3 示例China编程代码2. Tab

Nginx指令add_header和proxy_set_header的区别及说明

《Nginx指令add_header和proxy_set_header的区别及说明》:本文主要介绍Nginx指令add_header和proxy_set_header的区别及说明,具有很好的参考价... 目录Nginx指令add_header和proxy_set_header区别如何理解反向代理?proxy

Java中&和&&以及|和||的区别、应用场景和代码示例

《Java中&和&&以及|和||的区别、应用场景和代码示例》:本文主要介绍Java中的逻辑运算符&、&&、|和||的区别,包括它们在布尔和整数类型上的应用,文中通过代码介绍的非常详细,需要的朋友可... 目录前言1. & 和 &&代码示例2. | 和 ||代码示例3. 为什么要使用 & 和 | 而不是总是使

C++中函数模板与类模板的简单使用及区别介绍

《C++中函数模板与类模板的简单使用及区别介绍》这篇文章介绍了C++中的模板机制,包括函数模板和类模板的概念、语法和实际应用,函数模板通过类型参数实现泛型操作,而类模板允许创建可处理多种数据类型的类,... 目录一、函数模板定义语法真实示例二、类模板三、关键区别四、注意事项 ‌在C++中,模板是实现泛型编程

Spring中@RestController和@Controller的使用及区别

《Spring中@RestController和@Controller的使用及区别》:本文主要介绍Spring中@RestController和@Controller的使用及区别,具有很好的参考价... 目录Spring中@RestController和@Controller使用及区别1. 基本定义2. 使