前景檢測演算法(二)--codebook和平均背景法

來源:互聯網
上載者:User
原文:http://www.cnblogs.com/tornadomeet/archive/2012/04/08/2438158.html 前景檢測演算法_1(codebook和平均背景法)

      前景分割中一個非常重要的研究方向就是背景減圖法,因為背景減圖的方法簡單,原理容易被想到,且在智能視頻監控領域中,攝像機很多情況下是固定的,且背景也是基本不變或者是緩慢變換的,在這種場合背景減圖法的應用驅使了其不少科研人員去研究它。

      但是背景減圖獲得前景映像的方法缺點也很多:比如說光照因素,遮擋因素,動態周期背景,且背景非周期背景,且一般情況下我們考慮的是每個像素點之間獨立,這對實際應用留下了很大的隱患。

      這一小講主要是講簡單背景減圖法和codebook法。

 

一、簡單背景減圖法的工作原理。

      在視頻對背景進行建模的過程中,每2幀映像之間對應像素點灰階值算出一個誤差值,在背景建模時間內算出該像素點的平均值,誤差平均值,然後在平均差值的基礎上+-誤差平均值的常數(這個係數需要手動調整)倍作為背景映像的閾值範圍,所以當進行前景檢測時,當相應點位置來了一個像素時,如果來的這個像素的每個通道的灰階值都在這個閾值範圍內,則認為是背景用0表示,否則認為是前景用255表示。

      下面的一個工程是learning opencv一書中作者提供的原始碼,關於簡單背景減圖的代碼和注釋如下:

     avg_background.h檔案:

 1 /////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 2 // Accumulate average and ~std (really absolute difference) image and use this to detect background and foreground 3 // 4 // Typical way of using this is to: 5 //     AllocateImages(); 6 ////loop for N images to accumulate background differences 7 //    accumulateBackground(); 8 ////When done, turn this into our avg and std model with high and low bounds 9 //    createModelsfromStats();10 ////Then use the function to return background in a mask (255 == foreground, 0 == background)11 //    backgroundDiff(IplImage *I,IplImage *Imask, int num);12 ////Then tune the high and low difference from average image background acceptance thresholds13 //    float scalehigh,scalelow; //Set these, defaults are 7 and 6. Note: scalelow is how many average differences below average14 //    scaleHigh(scalehigh);15 //    scaleLow(scalelow);16 ////That is, change the scale high and low bounds for what should be background to make it work.17 ////Then continue detecting foreground in the mask image18 //    backgroundDiff(IplImage *I,IplImage *Imask, int num);19 //20 //NOTES: num is camera number which varies from 0 ... NUM_CAMERAS - 1.  Typically you only have one camera, but this routine allows21 //          you to index many.22 //23 #ifndef AVGSEG_24 #define AVGSEG_25 26 27 #include "cv.h"                // define all of the opencv classes etc.28 #include "highgui.h"29 #include "cxcore.h"30 31 //IMPORTANT DEFINES:32 #define NUM_CAMERAS   1              //This function can handle an array of cameras33 #define HIGH_SCALE_NUM 7.0            //How many average differences from average image on the high side == background34 #define LOW_SCALE_NUM 6.0        //How many average differences from average image on the low side == background35 36 void AllocateImages(IplImage *I);37 void DeallocateImages();38 void accumulateBackground(IplImage *I, int number=0);39 void scaleHigh(float scale = HIGH_SCALE_NUM, int num = 0);40 void scaleLow(float scale = LOW_SCALE_NUM, int num = 0);41 void createModelsfromStats();42 void backgroundDiff(IplImage *I,IplImage *Imask, int num = 0);43 44 #endif

 

     avg_background.cpp檔案:

  1 // avg_background.cpp : 定義控制台應用程式的進入點。  2 //  3   4 #include "stdafx.h"  5 #include "avg_background.h"  6   7   8 //GLOBALS  9  10 IplImage *IavgF[NUM_CAMERAS],*IdiffF[NUM_CAMERAS], *IprevF[NUM_CAMERAS], *IhiF[NUM_CAMERAS], *IlowF[NUM_CAMERAS]; 11 IplImage *Iscratch,*Iscratch2,*Igray1,*Igray2,*Igray3,*Imaskt; 12 IplImage *Ilow1[NUM_CAMERAS],*Ilow2[NUM_CAMERAS],*Ilow3[NUM_CAMERAS],*Ihi1[NUM_CAMERAS],*Ihi2[NUM_CAMERAS],*Ihi3[NUM_CAMERAS]; 13  14 float Icount[NUM_CAMERAS]; 15  16 void AllocateImages(IplImage *I)  //I is just a sample for allocation purposes 17 { 18     for(int i = 0; i<NUM_CAMERAS; i++){ 19         IavgF[i] = cvCreateImage( cvGetSize(I), IPL_DEPTH_32F, 3 ); 20         IdiffF[i] = cvCreateImage( cvGetSize(I), IPL_DEPTH_32F, 3 ); 21         IprevF[i] = cvCreateImage( cvGetSize(I), IPL_DEPTH_32F, 3 ); 22         IhiF[i] = cvCreateImage( cvGetSize(I), IPL_DEPTH_32F, 3 ); 23         IlowF[i] = cvCreateImage(cvGetSize(I), IPL_DEPTH_32F, 3 ); 24         Ilow1[i] = cvCreateImage( cvGetSize(I), IPL_DEPTH_32F, 1 ); 25         Ilow2[i] = cvCreateImage( cvGetSize(I), IPL_DEPTH_32F, 1 ); 26         Ilow3[i] = cvCreateImage( cvGetSize(I), IPL_DEPTH_32F, 1 ); 27         Ihi1[i] = cvCreateImage( cvGetSize(I), IPL_DEPTH_32F, 1 ); 28         Ihi2[i] = cvCreateImage( cvGetSize(I), IPL_DEPTH_32F, 1 ); 29         Ihi3[i] = cvCreateImage( cvGetSize(I), IPL_DEPTH_32F, 1 ); 30         cvZero(IavgF[i]  ); 31         cvZero(IdiffF[i]  ); 32         cvZero(IprevF[i]  ); 33         cvZero(IhiF[i] ); 34         cvZero(IlowF[i]  );         35         Icount[i] = 0.00001; //Protect against divide by zero 36     } 37     Iscratch = cvCreateImage( cvGetSize(I), IPL_DEPTH_32F, 3 ); 38     Iscratch2 = cvCreateImage( cvGetSize(I), IPL_DEPTH_32F, 3 ); 39     Igray1 = cvCreateImage( cvGetSize(I), IPL_DEPTH_32F, 1 ); 40     Igray2 = cvCreateImage( cvGetSize(I), IPL_DEPTH_32F, 1 ); 41     Igray3 = cvCreateImage( cvGetSize(I), IPL_DEPTH_32F, 1 ); 42     Imaskt = cvCreateImage( cvGetSize(I), IPL_DEPTH_8U, 1 ); 43  44     cvZero(Iscratch); 45     cvZero(Iscratch2 ); 46 } 47  48 void DeallocateImages() 49 { 50     for(int i=0; i<NUM_CAMERAS; i++){ 51         cvReleaseImage(&IavgF[i]); 52         cvReleaseImage(&IdiffF[i] ); 53         cvReleaseImage(&IprevF[i] ); 54         cvReleaseImage(&IhiF[i] ); 55         cvReleaseImage(&IlowF[i] ); 56         cvReleaseImage(&Ilow1[i]  ); 57         cvReleaseImage(&Ilow2[i]  ); 58         cvReleaseImage(&Ilow3[i]  ); 59         cvReleaseImage(&Ihi1[i]   ); 60         cvReleaseImage(&Ihi2[i]   ); 61         cvReleaseImage(&Ihi3[i]  ); 62     } 63     cvReleaseImage(&Iscratch); 64     cvReleaseImage(&Iscratch2); 65  66     cvReleaseImage(&Igray1  ); 67     cvReleaseImage(&Igray2 ); 68     cvReleaseImage(&Igray3 ); 69  70     cvReleaseImage(&Imaskt); 71 } 72  73 // Accumulate the background statistics for one more frame 74 // We accumulate the images, the image differences and the count of images for the  75 //    the routine createModelsfromStats() to work on after we're done accumulating N frames. 76 // I        Background image, 3 channel, 8u 77 // number    Camera number 78 void accumulateBackground(IplImage *I, int number) 79 { 80     static int first = 1; 81     cvCvtScale(I,Iscratch,1,0); //To float;#define cvCvtScale cvConvertScale #define cvScale cvConvertScale 82     if (!first){ 83         cvAcc(Iscratch,IavgF[number]);//將2幅映像相加:IavgF[number]=IavgF[number]+Iscratch,IavgF[]裡面裝的是時間順序圖表片的累加 84         cvAbsDiff(Iscratch,IprevF[number],Iscratch2);//將2幅映像相減:Iscratch2=abs(Iscratch-IprevF[number]); 85         cvAcc(Iscratch2,IdiffF[number]);//IdiffF[]裡面裝的是映像差的累積和 86         Icount[number] += 1.0;//累積的圖片幀數計數 87     } 88     first = 0; 89     cvCopy(Iscratch,IprevF[number]);//執行完該函數後,將當前幀資料儲存為前一幀資料 90 } 91  92 // Scale the average difference from the average image high acceptance threshold 93 void scaleHigh(float scale, int num)//設定背景建模時的高閾值函數 94 { 95     cvConvertScale(IdiffF[num],Iscratch,scale); //Converts with rounding and saturation 96     cvAdd(Iscratch,IavgF[num],IhiF[num]);//將平均累積映像與誤差累積映像縮放scale倍然後再相加 97     cvCvtPixToPlane( IhiF[num], Ihi1[num],Ihi2[num],Ihi3[num], 0 );//#define cvCvtPixToPlane cvSplit,且cvSplit是將一個多通道矩陣轉換為幾個單通道矩陣 98 } 99 100 // Scale the average difference from the average image low acceptance threshold101 void scaleLow(float scale, int num)//設定背景建模時的低閾值函數102 {103     cvConvertScale(IdiffF[num],Iscratch,scale); //Converts with rounding and saturation104     cvSub(IavgF[num],Iscratch,IlowF[num]);//將平均累積映像與誤差累積映像縮放scale倍然後再相減105     cvCvtPixToPlane( IlowF[num], Ilow1[num],Ilow2[num],Ilow3[num], 0 );106 }107 108 //Once you've learned the background long enough, turn it into a background model109 void createModelsfromStats()110 {111     for(int i=0; i<NUM_CAMERAS; i++)112     {113         cvConvertScale(IavgF[i],IavgF[i],(double)(1.0/Icount[i]));//此處為求出累積求和映像的平均值114         cvConvertScale(IdiffF[i],IdiffF[i],(double)(1.0/Icount[i]));//此處為求出累計誤差映像的平均值115         cvAddS(IdiffF[i],cvScalar(1.0,1.0,1.0),IdiffF[i]);  //Make sure diff is always something,cvAddS是用於一個數值和一個標量相加116         scaleHigh(HIGH_SCALE_NUM,i);//HIGH_SCALE_NUM初始定義為7,其實就是一個倍數117         scaleLow(LOW_SCALE_NUM,i);//LOW_SCALE_NUM初始定義為6118     }119 }120 121 // Create a binary: 0,255 mask where 255 means forground pixel122 // I        Input image, 3 channel, 8u123 // Imask    mask image to be created, 1 channel 8u124 // num        camera number.125 //126 void backgroundDiff(IplImage *I,IplImage *Imask, int num)  //Mask should be grayscale127 {128     cvCvtScale(I,Iscratch,1,0); //To float;129 //Channel 1130     cvCvtPixToPlane( Iscratch, Igray1,Igray2,Igray3, 0 );131     cvInRange(Igray1,Ilow1[num],Ihi1[num],Imask);//Igray1[]中相應的點在Ilow1[]和Ihi1[]之間時,Imask中相應的點為255(背景符合)132 //Channel 2133     cvInRange(Igray2,Ilow2[num],Ihi2[num],Imaskt);//也就是說對於每一幅映像的絕對值差小於絕對值差平均值的6倍或者大於絕對值差平均值的7倍被認為是前景映像134     cvOr(Imask,Imaskt,Imask);135     //Channel 3136     cvInRange(Igray3,Ilow3[num],Ihi3[num],Imaskt);//這裡的固定閾值6和7太不合理了,還好工程後面可以根據實際情況手動調整。137     cvOr(Imask,Imaskt,Imask);138     //Finally, invert the results139     cvSubRS( Imask, cvScalar(255), Imask);//前景用255表示了,背景是用0表示140 }

 

 二、codebook演算法工作原理

     考慮到簡單背景減圖法無法對動態背景建模,有學者就提出了codebook演算法。

     該演算法為映像中每一個像素點建立一個碼本,每個碼本可以包括多個碼元,每個碼元有它的學習時最大最小閾值,檢測時的最大最小閾值等成員。在背景建模期間,每當來了一幅新圖片,對每個像素點進行碼本匹配,也就是說如果該像素值在碼本中某個碼元的學習閾值內,則認為它離過去該對應點出現過的曆史情況偏離不大,通過一定的像素值比較,如果滿足條件,此時還可以更新對應點的學習閾值和檢測閾值。如果新來的像素值對碼本中每個碼元都不匹配,則有可能是由於背景是動態,所以我們需要為其建立一個新的碼元,並且設定相應的碼元成員變數。因此,在背景學習的過程中,每個像素點可以對應多個碼元,這樣就可以學到複雜的動態背景。

     關於codebook演算法的代碼和注釋如下:

     cv_yuv_codebook.h檔案:

 1 /////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 2 // Accumulate average and ~std (really absolute difference) image and use

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.