背景建模之单高斯实现
高斯分布與背景建模的關(guān)系:圖像中每一個(gè)像素點(diǎn)的顏色值作為一個(gè)隨機(jī)過(guò)程X,并假設(shè)該點(diǎn)的像素值出現(xiàn)的概率服從高斯分布。令I(lǐng)(x,y,t)表示像素點(diǎn)(x,y,t)在t時(shí)刻的像素值,則有:
其中和分別為t時(shí)刻該像素高斯分布的期望值和標(biāo)準(zhǔn)差。
算法流程:
1.用第一幀圖像數(shù)據(jù)初始化背景模型,其中std_init通常設(shè)置為20。
2.檢測(cè)前景與背景像素。
背景像素檢測(cè)公式:
前景像素檢測(cè)公式:
3.對(duì)、、背景值進(jìn)行更新,更新公式如下:
4.返回到2直至停止。
算法實(shí)現(xiàn)代碼(vc6.0+opencv1.0):
// singleGaussian.cpp : Defines the entry point for the console application.
#include "stdafx.h"
#include <highgui.h>
#include <cv.h>
#include <math.h>
#include <cxcore.h>
int main(int argc, char* argv[])
{
//新建窗口
? ? cvNamedWindow("origin", CV_WINDOW_AUTOSIZE);
? ? cvNamedWindow("background", CV_WINDOW_AUTOSIZE);
? ? cvNamedWindow("foreground", CV_WINDOW_AUTOSIZE);
? ? double alpha = 0.05; ? ?//背景建模alpha值
? ? double std_init = 20; ? ?//初始標(biāo)準(zhǔn)差
? ? double var_init = std_init * std_init; ? ?//初始方差 ? ?
? ? double lamda = 2.5 * 1.2; ? ?//背景更新參數(shù)
? ? //視頻文件
? ? CvCapture *capture = NULL;
? ? //讀取視頻文件
? ? if (argc == 1)
? ? {
? ? ? ? //從攝像頭讀入
? ? ? ? capture = cvCreateCameraCapture(0);
? ? }
? ? else if (argc == 2)
? ? {
? ? ? ? //從文件讀入
? ? ? ? capture = cvCreateFileCapture(argv[1]);
? ? }
? ? else
? ? {
? ? ? ? //讀入錯(cuò)誤
? ? ? ? printf("input error\n");
? ? ? ? return -1;
? ? }
? ? IplImage *frame = NULL; ? ? ? ?//原始圖像
? ? IplImage *frame_u = NULL; ? ?//期望圖像
? ? IplImage *frame_d = NULL; ? ?//前景圖像
? ? IplImage *frame_var = NULL; ? ?//方差圖像
? ? IplImage *frame_std = NULL; ? ?//標(biāo)準(zhǔn)差
? ? CvScalar pixel = {0}; ? ? ? ?//像素原始值
? ? CvScalar pixel_u = {0}; ? ? ? ?//像素期望
? ? CvScalar pixel_d = {0}; ? ? ? ?//像素前景
? ? CvScalar pixel_var = {0}; ? ?//像素方差
? ? CvScalar pixel_std = {0}; ? ?//像素標(biāo)準(zhǔn)差
? ? //初始化frame_u, frame_var, frame_std
? ? frame = cvQueryFrame(capture);
? ? frame_u = cvCreateImage(cvSize(frame->width, frame->height), IPL_DEPTH_8U, 3);
? ? frame_d = 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_d.val[0] = 0;
? ? ? ? ? ? pixel_d.val[1] = 0;
? ? ? ? ? ? pixel_d.val[2] = 0;
? ? ? ? ? ? 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_d, y, x, pixel_d);
? ? ? ? ? ? cvSet2D(frame_var, y, x, pixel_var);
? ? ? ? ? ? cvSet2D(frame_std, y, x, pixel_std);
? ? ? ? }
? ? }
? ? while (cvWaitKey(33) != 27) ? ? ? ?//按ESC鍵退出, 幀率33ms
? ? {
? ? ? ? frame = cvQueryFrame(capture);
? ? ? ? //視頻結(jié)束退出
? ? ? ? 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_d = cvGet2D(frame_d, y, x);
? ? ? ? ? ? ? ? pixel_std = cvGet2D(frame_std, y, x);
? ? ? ? ? ? ? ? pixel_var = cvGet2D(frame_var, y, x);
? ? ? ? ? ? ? ? //|I-u| < lamda*std 時(shí)認(rèn)為是背景, 進(jìn)行更新
? ? ? ? ? ? ? ? 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]);
? ? ? ? ? ? ? ? ? ? //更新標(biāo)準(zhǔn)差
? ? ? ? ? ? ? ? ? ? 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]);
? ? ? ? ? ? ? ? ? ? //寫(xiě)入矩陣
? ? ? ? ? ? ? ? ? ? cvSet2D(frame_u, y, x, pixel_u);
? ? ? ? ? ? ? ? ? ? cvSet2D(frame_var, y, x, pixel_var);
? ? ? ? ? ? ? ? ? ? cvSet2D(frame_std, y, x, pixel_std);
? ? ? ? ? ? ? ? }
? ? ? ? ? ? ? ? else
? ? ? ? ? ? ? ? {
? ? ? ? ? ? ? ? ? ? pixel_d.val[0] = pixel.val[0] - pixel_u.val[0];
? ? ? ? ? ? ? ? ? ??pixel_d.val[1] = pixel.val[1] - pixel_u.val[1];
? ? ? ? ? ? ? ? ? ? pixel_d.val[2] = pixel.val[2] - pixel_u.val[2];
? ? ? ? ? ? ? ? ? ? cvSet2D(frame_d, y, x, pixel_d);
? ? ? ? ? ? ? ?}
? ? ? ? ? ? }
? ? ? ? }
? ? ? ? //顯示結(jié)果
? ? ? ? frame_u->origin = 1;
? ? ? ? frame_d->origin = 1;
? ? ? ? cvShowImage("origin", frame);
? ? ? ? cvShowImage("background", frame_u);
? ? ? ? cvShowImage("foreground", frame_d);
? ? }
? ? //釋放內(nèi)存
? ? cvReleaseCapture(&capture);
? ? cvReleaseImage(&frame);
? ? cvReleaseImage(&frame_u);
? ? cvReleaseImage(&frame_var);
? ? cvReleaseImage(&frame_std);
? ? cvDestroyWindow("origin");
? ? cvDestroyWindow("background");
? ? cvDestroyWindow("foreground");
? ? return 0;
}
完善補(bǔ)充:
對(duì)于單高斯模型實(shí)現(xiàn)必須進(jìn)行背景減除與陰影消除的處理,實(shí)用的模型還需要很多改進(jìn)!此文僅供初學(xué)者研究。
參考鏈接:
http://underthehood.blog.51cto.com/2531780/484191
總結(jié)
以上是生活随笔為你收集整理的背景建模之单高斯实现的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 算法优化:rgb向yuv的转化最优算法,
- 下一篇: Bayer Pattern to RGB