NO IMAGE

轉自王先榮先生的部落格:http://www.cnblogs.com/xrwang/archive/2010/04/12/BackgroundGenerationAndForegroundDetectionPhase3.html

作者:王先榮

    在上一篇文章裡,我嘗試翻譯了《Nonparametric Background Generation》,本文主要介紹以下內容:如何實現該論文的演算法,如果利用該演算法來進行背景建模及前景檢測,最後談談我的一些體會。為了使描述更加簡便,以下將該論文的演算法及實現稱為NBGModel。
1 使用示例
    NBGModel在使用上非常的簡便,您可以仿照下面的程式碼來使用它:

複製程式碼
//初始化NBGModel物件
NBGModel nbgModel = new NBGModel(320, 240);
//訓練背景模型
nbgModel.TrainBackgroundModel(historyImages);
//前景檢測
nbgModel.Update(currentFrame);
//利用結果
pbResult.Image = nbgModel.ForegroundMask.Bitmap;
//釋放物件
nbgModel.Dispose();
複製程式碼

下面是更加完整的示例:

更加完整的示例

 

2 實現NBGModel
    2.1 我在實現NBGModel的時候基本上跟論文中的方式一樣,不過有以下兩點區別:
(1)論文中的MeanShift計算使用了Epanechnikov核函式,我使用的是矩形窗形式的MeanShift計算。主要是因為我自己不會實現MeanShift,只能利用OpenCV中提供的cvMeanShift函式。這樣做也有一個好處——不再需要計算與儲存典型點。
(2)論文中的方法在檢測的過程中聚集中心會不斷的增加,我模仿CodeBook的實現為其增加了一個清除消極聚集中心的ClearStable方法。這樣可以在必要的時候將長期不活躍的聚集中心清除掉。

    2.2 NBGModel中用到的資料成員如下所示:
        private int width;                                          //影象的寬度
        private int height;                                         //影象的高度
        private NBGParameter param;                                 //非引數背景模型的引數

        private List<Image<Ycc, Byte>> historyImages = null;        //歷史影象:列表個數為param.n,在更新時如果個數大於等於param.n,刪除最早的歷史影象,加入最新的歷史影象
        //由於這裡採用矩形視窗方式的MeanShift計算,因此不再需要分組影象的典型點。這跟論文不一樣。
        //private List<Image<Ycc,Byte>> convergenceImages = null;   //收斂影象:列表個數為param.m,僅在背景訓練時使用,訓練結束即被清空,因此這裡不再宣告
        private Image<Gray, Byte> sampleImage = null;               //樣本影象:儲存歷史影象中每個畫素在Y通道的值,用於MeanShift計算
        private List<ClusterCenter<Ycc>>[,] clusterCenters = null;  //聚集中心資料:將收斂點分類之後得到的聚集中心,陣列大小為:height x width,列表元素個數不定q(q<=m)。
        private Image<Ycc, Byte> mrbm = null;                       //最可靠背景模型

        private Image<Gray, Byte> backgroundMask = null;            //背景掩碼影象

        private double frameCount = 0;                              //總幀數(不包括訓練階段的幀數n)

其中,NBGParameter結構包含以下成員:
        public int n;                       //樣本數目:需要被保留的歷史影象數目
        public int m;                       //典型點數目:歷史影象需要被分為多少組
        public double theta;                //權重係數:權重大於該值的聚集中心為候選背景
        public double t;                    //最小差值:觀測值與候選背景的最小差值大於該值時,為前景;否則為背景
        public MCvTermCriteria criteria;    //Mean Shift計算的終止條件:包括最大迭代次數和終止計算的精度

聚集中心ClusterCenter使用類而不是結構,是為了方便更新,它包含以下成員:
        public TColor ci;              //聚集中心的畫素值
        public double wi;              //聚集中心的權重
        public double li;              //聚集中心包含的收斂點數目
        public double updateFrameNo;   //更新該聚集中心時的幀數:用於清除消極的聚集中心

    2.3 NBGModel中的關鍵流程
1.背景建模
(1)將訓練用的樣本影象新增到歷史影象historyImages中;
(2)將歷史影象分為m組,以每組所在位置的矩形窗為起點進行MeanShift計算,結果窗的中點為收斂中心,收斂中心的畫素值為收斂值,將收斂值新增到收斂影象convergenceImages中;
(3)計算收斂影象的聚集中心:(a)得到收斂中心的最小值Cmin;(b)將[0,Cmin t]區間中的收斂中心劃分為一類;(c)計算已分類收斂中心的平均值,作為聚集中心的值;(d)刪除已分類的收斂中心;(e)重複a~d,直到收斂中心全部歸類;
(4)得到最可靠背景模型MRBM:在聚集中心中選取wi最大的值作為某個畫素的最可靠背景。

2.前景檢測
(1)用wi≥theta作為條件選擇可能的背景組Cb;
(2)對每個觀測值x0,計算x0與Cb的最小差值d;
(3)如果d>t,則該點為前景;否則為背景。

3.背景維持
(1)如果某點為背景,更新最近聚集中心的wi為(li 1)/m;
(2)如果某點為前景:(a)以該點所在的矩形窗為起點進行MeanShift計算,可得到新的收斂中心Cnew(wi=1/m);(b)將Cnew加入到聚集中心clusterCenters;
(3)在必要的時候,清理消極的聚集中心。

    2.4 NBGModel的實現程式碼
值得注意的是:在實現程式碼中,有好幾個以2結尾的私有方法,它們主要用於演示演算法流程,實際上並未使用。為了優化效能而增加了不少指標操作之後的程式碼可讀性變得很差。

NBGModel實現程式碼

 

3 NBGModel類介紹
    3.1 屬性
Width——獲取影象的寬度
Height——獲取影象的高度
Param——獲取引數設定
Mrbm——獲取最可靠背景模型影象
BackgroundMask——獲取背景掩碼影象
ForegroundMask——獲取前景掩碼影象
FrameCount——獲取已被檢測的幀數

    3.2 建構函式
public NBGModel(int width, int height)——用預設的引數初始化NBGModel,等價於NBGModel(width, height, NBGParameter.GetDefaultNBGParameter())
public NBGModel(int width, int height, NBGParameter param)——用指定的引數初始化NBGModel

    3.3 方法
AddHistoryImage——新增一幅或者一組歷史影象
TrainBackgroundModel——訓練背景模型;如果傳入了歷史影象,則先新增歷史影象,然後再訓練背景模型
Update——更新背景模型,同時檢測前景
ClearStale——清除消極的聚集中心
Dispose——釋放資源

4 體會
    NBGModel的確非常有效,非常簡潔,特別適用於伴隨複雜運動物件的背景建模。我特意選取了PETS2009中的素材對其做了一些測試,結果也證明了NBGModel的優越性。不過需要指出的是,它需要佔用大量的記憶體(主要因為需要儲存n幅歷史影象);它的計算量比較大。
在使用的過程中,它始終需要在記憶體中快取n幅歷史影象,1幅最可靠背景模型影象,1幅背景掩碼影象,近似m幅影象(聚集中心);而在訓練階段,更需要臨時儲存m幅收斂影象。
例如:樣本數目為100,典型點數目為10,影象尺寸為768×576時,所用的記憶體接近300M,訓練背景需要大約需要33秒,而對每幅影象進行前景檢測大約需要600ms。雖然可以使用並行程式設計來提高效能,但是並不能從根本上解決問題。
(注:測試電腦的CPU為AMD閃龍3200 ,記憶體1.5G。)
    看來,有必要研究一種新的方法,目標是檢測效果更好,記憶體佔用低,處理更快速。目前的想法是使用《Wallflower: Principles and Practice of Background Manitenance》中的3層架構(時間軸上的畫素級處理,畫素間的區域處理,幀間處理),但是對每層架構都選用目前流行的處理方式,並對處理方式進行優化。時間軸上的畫素級處理打算使用CodeBook方法,但是增加本文的一些思想。畫素間的區域處理打算參考《基於區域相關的核函式背景建模演算法》中的方法。幀間處理預計會採用全域性灰度統計值作為依據。

最後,按照慣例:感謝您耐心看完本文,希望對您有所幫助。
本文所述方法及程式碼僅用於學習研究,不得用於商業目的。