平均背景模型

背景建模法是一种简单、快速但是背景的多模态(比如光照强度的变化、树叶的摇动等)比较敏感的一种背景建模方法。其基本思想是计算每个像素上的平均值作为基本模型,然后将当前像素值和背景像素值进行比较,当他们之间的差值小于某个特定的阈值TH时,则该像素可以被认为是背景像素,否则被认为是前景目标像素。其中,阈值TH可以自己根据经验设定,也可以采用自适应算法进行确定。可以很容易看出,这种方法对于背景的突发变化很敏感,而且实验证明,它对于和背景颜色相近的前景目标的检测效果也不理想,仅可作为参考。

#include <iostream>
#include<opencv2/opencv.hpp>
using namespace std;

int main()
{
    cvNamedWindow("video");
    cvNamedWindow("avg");
    cvNamedWindow("sub");

    cvMoveWindow("video",0,0);
    cvMoveWindow("avg",330,0);
    cvMoveWindow("sub",660,0);

    CvCapture *capture=NULL;
    capture=cvCaptureFromFile("video.avi");

    IplImage *pFrame=NULL;
    IplImage* pFrImg = NULL;
    IplImage* pBkImg = NULL;

    CvMat* pFrameMat = NULL;
    CvMat* pFrMat = NULL;
    CvMat* pBkMat = NULL;

    int numfrm=0;
    while(pFrame=cvQueryFrame(capture))
    {
        numfrm++;
        if(numfrm==1)
        {
            pBkImg = cvCreateImage(cvSize(pFrame->width, pFrame->height),  IPL_DEPTH_8U,1);
            cvCvtColor(pFrame,pBkImg,CV_BGR2GRAY);

            pFrMat = cvCreateMat(pFrame->height, pFrame->width, CV_32FC1);
            pBkMat = cvCreateMat(pFrame->height, pFrame->width, CV_32FC1);
            //cvConvert函数用于图像和矩阵之间的相互转换 为什么要用cvConvert 把IplImage转为矩阵? 因为IplImage里的数据,你只能用uchar的形式存放,
            //当你需要这些图像数据看作数据矩阵来运算时,0~255的精度显然满足不了要求; 然而CvMat里却可以存放任意通道数、任意格式的数据,
            //这个机制方便了研究中的这种需求,转化为矩阵就可以进行更自由的计算。
            cvConvert(pBkImg, pFrMat);
            cvConvert(pBkImg, pBkMat);
            cvRunningAvg(pFrMat,pBkMat,0.005,0);

            cvConvert(pBkMat, pBkImg);
            cvShowImage("avg",pBkImg);
            if(cvWaitKey(20)==27)
                    return -1;

        }
        else
        {
            cvCvtColor(pFrame,pBkImg,CV_BGR2GRAY);
            cvConvert(pBkImg, pFrMat);
            //        cvRunningAvg函数是opencv库中的一个函数。
            //        作用:用来更新移动平均。
            //        函数形式:
            //        void cvRunningAvg(const CvArr * image, CvArr* acc, double alpha, const CvArr* mask=NULL)
            //        参数说明:
            //        image:输入图像,1或3通道,8比特或32比特的float型
            //        acc:累加器,和image一样大小
            //        alpha:更新时,image所占的权重
            //        mask:操作符掩码
            //        if mask(x,y)!= 0 (1-alpha)*acc(x,y)+alpha*image(x,y) =>acc(x,y)
            //        cvRunningAvg();
            cvRunningAvg(pFrMat,pBkMat,0.005,0);

            cvConvert(pBkMat, pBkImg);
            cvShowImage("avg",pBkImg);
            if(cvWaitKey(20)==27)
                    return -1;
        }
    }

    capture=cvCaptureFromFile("video.avi");
    numfrm=0;
    while(pFrame=cvQueryFrame(capture))
    {
        numfrm++;
        if(numfrm==1)
        {
               pFrImg = cvCreateImage(cvSize(pFrame->width, pFrame->height),  IPL_DEPTH_8U,1);
               pFrameMat = cvCreateMat(pFrame->height, pFrame->width, CV_32FC1);

               cvCvtColor(pFrame,pFrImg,CV_BGR2GRAY);
               cvConvert(pFrImg,pFrameMat);

               cvAbsDiff(pFrameMat,pBkMat,pFrMat);
               cvThreshold(pFrMat, pFrImg, 60, 255.0, CV_THRESH_BINARY);
               cvShowImage("video",pFrame);
               cvvShowImage("sub",pFrImg);
        }
        else
        {
            cvCvtColor(pFrame,pFrImg,CV_BGR2GRAY);
            cvConvert(pFrImg,pFrameMat);

            cvAbsDiff(pFrameMat,pBkMat,pFrMat);
            cvThreshold(pFrMat, pFrImg, 60, 255.0, CV_THRESH_BINARY);
            cvShowImage("video",pFrame);
            cvvShowImage("sub",pFrImg);
        }

        if(cvWaitKey(20)==27)
            break;
    }


    cvReleaseImage(&pFrame);
    cvReleaseImage(&pFrImg);
    cvReleaseImage(&pBkImg);
    cvReleaseMat(&pFrameMat);
    cvReleaseMat(&pFrMat);
    cvReleaseMat(&pBkMat);
    cvReleaseCapture(&capture);
    cvDestroyWindow("video");
    cvDestroyWindow("avg");
    cvDestroyWindow("sub");
    return 0;
}

 程序运行结果:

 

原文地址:https://www.cnblogs.com/juaner767/p/3678611.html