Chinaunix首页 | 论坛 | 博客
  • 博客访问: 191914
  • 博文数量: 53
  • 博客积分: 2015
  • 博客等级: 上尉
  • 技术积分: 546
  • 用 户 组: 普通用户
  • 注册时间: 2009-05-04 23:28
文章分类

全部博文(53)

文章存档

2012年(4)

2011年(8)

2010年(19)

2009年(22)

我的朋友

分类: C/C++

2010-01-22 21:13:39

/*******************单高斯背景建模v1.0*************************
************************2010.01.22****************************/


#include <highgui.h>
#include <cv.h>
#include <math.h>
#include <stdio.h>
#include <stdlib.h>

int main(int argc, char **argv)
{
    //新建窗口
    cvNamedWindow("origin", CV_WINDOW_AUTOSIZE);
    cvNamedWindow("processing", CV_WINDOW_AUTOSIZE);

    double alpha = 0.05;    //背景建模alpha值
    double std_init = 20;    //初始标准差
    double var_init = std_init * std_init;    //初始方差    
    double lamda = 2.5 * 1.2;    //背景更新参数


    //视频文件
    CvCapture *capture = NULL;

    //读取视频文件
    if (argc == 1)
    {
        //从摄像头读入
        capture = cvCreateCameraCapture(0);
    }
    else if (argc == 2)
    {
        //从文件读入
        capture = cvCreateFileCapture(argv[1]);
    }
    else
    {
        //读入错误
        printf("input error\n");
        return -1;
    }

    IplImage *frame = NULL;        //原始图像
    IplImage *frame_u = NULL;    //期望图像
    IplImage *frame_var = NULL;    //方差图像
    IplImage *frame_std = NULL;    //标准差

    CvScalar pixel = {0};        //像素原始值
    CvScalar pixel_u = {0};        //像素期望
    CvScalar pixel_var = {0};    //像素方差
    CvScalar pixel_std = {0};    //像素标准差

    //初始化frame_u, frame_var, frame_std
    frame = cvQueryFrame(capture);
    frame_u = cvCreateImage(cvSize(frame->width, frame->height), IPL_DEPTH_8U, 3);
    frame_var = cvCreateImage(cvSize(frame->width, frame->height), IPL_DEPTH_8U, 3);
    frame_std = cvCreateImage(cvSize(frame->width, frame->height), IPL_DEPTH_8U, 3);

    for (int y = 0; y < frame->height; ++y)
    {
        for (int x = 0; x < frame->width; ++x)
        {
            pixel = cvGet2D(frame, y, x);

            pixel_u.val[0] = pixel.val[0];
            pixel_u.val[1] = pixel.val[1];
            pixel_u.val[2] = pixel.val[2];

            pixel_std.val[0] = std_init;
            pixel_std.val[1] = std_init;
            pixel_std.val[2] = std_init;

            pixel_var.val[0] = var_init;
            pixel_var.val[1] = var_init;
            pixel_var.val[2] = var_init;

            cvSet2D(frame_u, y, x, pixel_u);
            cvSet2D(frame_var, y, x, pixel_var);
            cvSet2D(frame_std, y, x, pixel_std);
        }
    }

    while (cvWaitKey(33) != 27)        //按ESC键退出, 帧率33ms
    {
        frame = cvQueryFrame(capture);

        //视频结束退出
        if (!frame)
        {
            break;
        }

        //单高斯背景更新
        for (int y = 0; y < frame->height; ++y)
        {
            for (int x = 0; x < frame->width; ++x)
            {
                pixel = cvGet2D(frame, y, x);
                pixel_u = cvGet2D(frame_u, y, x);
                pixel_std = cvGet2D(frame_std, y, x);
                pixel_var = cvGet2D(frame_var, y, x);

                //|I-u| < lamda*std 时认为是背景, 进行更新
                if (fabs(pixel.val[0] - pixel_u.val[0]) < lamda * pixel_std.val[0] &&
                    fabs(pixel.val[1] - pixel_u.val[1]) < lamda * pixel_std.val[1] &&
                    fabs(pixel.val[2] - pixel_u.val[2]) < lamda * pixel_std.val[2])
                {
                    //更新期望 u = (1-alpha)*u + alpha*I
                    pixel_u.val[0] = (1 - alpha) * pixel_u.val[0] + alpha * pixel.val[0];
                    pixel_u.val[1] = (1 - alpha) * pixel_u.val[1] + alpha * pixel.val[1];
                    pixel_u.val[2] = (1 - alpha) * pixel_u.val[2] + alpha * pixel.val[2];

                    //更新方差 var = (1-alpha)*var + alpha*(I-u)^2
                    pixel_var.val[0] = (1 - alpha) * pixel_var.val[0] +
                                    (pixel.val[0] - pixel_u.val[0]) * (pixel.val[0] - pixel_u.val[0]);
                    pixel_var.val[1] = (1 - alpha) * pixel_var.val[1] +
                                    (pixel.val[1] - pixel_u.val[1]) * (pixel.val[1] - pixel_u.val[1]);
                    pixel_var.val[2] = (1 - alpha) * pixel_var.val[2] +
                                    (pixel.val[2] - pixel_u.val[2]) * (pixel.val[2] - pixel_u.val[2]);

                    //更新标准差
                    pixel_std.val[0] = sqrt(pixel_var.val[0]);
                    pixel_std.val[1] = sqrt(pixel_var.val[1]);
                    pixel_std.val[2] = sqrt(pixel_var.val[2]);

                    //写入矩阵
                    cvSet2D(frame_u, y, x, pixel_u);
                    cvSet2D(frame_var, y, x, pixel_var);
                    cvSet2D(frame_std, y, x, pixel_std);
                }
            }
        }

        //显示结果
        cvShowImage("origin", frame);
        cvShowImage("processing", frame_u);
    }

    //释放内存
    cvReleaseCapture(&capture);
    cvReleaseImage(&frame);
    cvReleaseImage(&frame_u);
    cvReleaseImage(&frame_var);
    cvReleaseImage(&frame_std);
    cvDestroyWindow("origin");
    cvDestroyWindow("processing");

    return 0;
}


阅读(7012) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~