NO IMAGE

轉自王先榮先生的部落格:http://www.cnblogs.com/xrwang/archive/2012/04/24/MPCBBGM.html

多階編碼本模型(Multi phase codebook model)
作者:王先榮

 注:這是2010年所寫的文章,因為要發論文到雜誌上的緣故,這篇文章放到部落格幾天便隱藏起來了,最近論文正是刊出,所以文章又重見天日了。您可以在後面的地址檢視或者下載論文。

http://www.ceaj.org/Jweb_gcyyy/CN/abstract/abstract27730.shtml

前言
    本文將介紹一種名為多階編碼本的背景模型,該模型借用《Wallflower:Principles and Practice of Background Maintenance》中的三層模型思路,試圖達到適應性更廣,更精確,效能更好的目標。畫素級處理採用《Real-time foreground-background segmentation using codebook model》中提出的編碼本模型,不過對其進行了必要的擴充套件;區域級處理採用《學習OpenCV》中的形態學及輪廓處理方法;幀間處理以每幀的全域性平均灰度值為依據,動態建立多個編碼本以適應各種情況。因為部落格文章格式比較隨意,我在這裡只寫出要點,並給出實現程式碼,套話之類的都省了。

 

題外話
    在開始正文之前,我要向大家隆重的介紹一幅我女兒的作品,畫中有一座城堡及四個人,分別代表家、王子(??)、公主(女兒)、國王(我)及王后(我老婆)。最近在小孩身上連續發生了一些問題,希望能儘快好起來。


幀間處理
    幀間處理的目的是為了讓背景模型能適應儘可能的場景(相對固定及多變的場景)。在更新背景模型及背景減除的之前,需要先計算影象的全域性平均灰度值,然後根據平均灰度值選擇(或建立)一個合適的編碼本,並在選定的編碼本中執行更新或者減除。如果需要,也可以選擇關閉幀間處理,這樣多階編碼本模型就退化成編碼本模型。多個編碼本分別對應場景的多種可能。為了能夠鑑別編碼本的適用範圍,增加了兩個成員,分別是:ymin——最小灰度值,ymax——最大灰度值。在訓練背景模型的過程中,ymin和ymax可能會緩慢的擴充套件。


畫素級處理
    畫素級處理本質上是對編碼本模型的處理,每個畫素可能包含多個碼元(CodeWord),每個碼元的box上限和下限包容了畫素值的小幅度變化,多個碼元包容了畫素的多種可能性。為了能夠反映每個碼元的重要性,我為碼元增加了成員weight(權重);而為了計算出權重,又為碼元增加了成員frequency(表示該碼元出現的次數),為編碼本增加了成員frequencyCounts(用來儲存每個畫素中所有碼元的出現次數之和)。編碼本的詳細介紹請看kim的論文。增加權重和碼元出現次數的靈感來自《Nonparametric
Background Generation》,詳見原文或者我翻譯的博文。


區域級處理
    這裡的區域級處理跟通常的不太一樣,並非在建模和背景減除時進行採用區域級資訊。而是在背景減除之後,使用區域級處理對結果進行加工,達到消除噪聲、雜點及過小目標的目的。為什麼不在背景建模及背景減除時使用區域級資訊呢?原因有兩點:(1)為了使計算量不至於過大;(2)即使糅合了區域級資訊,結果也沒有顯著的改善。


演算法主要流程
1.更新背景模型
    (1)計算影象的全域性平均灰度值;
    (2)根據全域性平均灰度值選擇合適的編碼本;
    (3)如果沒有找到合適的編碼本,則建立一個新的編碼本;
    (4)在合適的編碼本或者新編碼本中,遍歷每個畫素;
    (5)遍歷每個碼元,尋找匹配當前畫素值的碼元;
    (6)如果找到了匹配的碼元,則更新匹配碼元及不匹配的碼元;
    (7)如果沒有找到匹配的碼元,則新增一個碼元,並更新不匹配的碼元。
2.背景減除
    (1)計算影象的全域性平均灰度值;
    (2)根據全域性平均灰度值選擇合適的編碼本;
    (3)如果沒有找到合適的編碼本,則認為所有的畫素都是前景;
    (4)如果找到了合適的編碼本,遍歷每個畫素;
    (5)遍歷每個碼元,如果存在匹配畫素當前值的碼元,則該畫素為背景;如果沒有匹配的碼元,則畫素為背景。
3.區域級處理
    (1)用形態學開、閉操作消除影象中的雜點和噪聲;
    (2)用輪廓操作來剔除過小的前景:遍歷影象的每個輪廓,如果輪廓的周長小於閥值,則剔除該輪廓;用多邊形或者凸包近似餘下的輪廓;重新繪製近似輪廓。
4.獲取最可靠背景
    (1)選擇命中次數最多的編碼本;
    (2)遍歷每個畫素,選擇畫素中權重最大的碼元;
    (3)將最佳碼元中box的平均值作為畫素值。
5.清除背景模型中消極或權重過小的碼元
    (1)遍歷每個編碼本,若編碼本的tAfterClear大於閥值,則執行清除;
    (2)遍歷需要清除編碼本中的每個畫素;
    (3)遍歷每個碼元,若消極幀數大於閥值,或者權重小於閥值,則刪除碼元;
    (4)重新計算相關的資料。
6.查表技巧
    在處理的過程中,為了提高計算畫素擴充套件值的速度,採用查表的做法來代替每次都計算:在初始化時先計算好256種可能的擴充套件值並存入陣列,然後再直接從陣列中取值。


如何使用多階編碼本模型
    您可以按下列方式來使用編碼本模型:

複製程式碼

//(1)初始化編碼本模型
MultiPhaseCodeBookModel mpcbModel =new MultiPhaseCodeBookModel(imageWidth,
imageHeight);
//(2)為了訓練背景模型而多次更新背景模型,訓練次數自己決定
mpcbModel.Update(image);
//(3)執行背景減除
mpcbModel.Diff(image2);
//(4)使用結果(前景掩碼影象)
pictureBox1.Image = mpcbModel.ForegroundMask.Bitmap;
//(5)結束時釋放資源
mpcbModel.Dispose();

複製程式碼

    完整的示例請參看下列程式碼:

使用多階編碼本模型——完整示例


使用參考
    1.MultiPhaseCodeBookModel類包含以下公共屬性:
int Width;                      //獲取影象的寬度
int Height;                     //獲取影象的高度
MultiPhaseCodeBookModelParameter Parameter; //獲取或者設定多階編碼本模型引數
List<CodeBook> CodeBooks;       //獲取編碼本列表
double TotalFrameCount;             //獲取已經更新的總幀數
Image<Gray, Byte> ForegroundMask;   //獲取前景掩碼影象
    2.MultiPhaseCodeBookModel類包含以下公共方法:
ClearStale——清除消極或者權重過小的碼元
Diff——背景減除
GetAverageGrayValue——獲取影象的全域性平均灰度值
GetMrbm——獲取最可靠背景影象
Update——更新背景模型
UpdateAndDiff——更新背景模型,然後執行背景減除


實現多階編碼本模型
    實現方法遵循上面提到的演算法,完整的多階編碼本模型實現程式碼如下所示:

實現多階編碼本模型


試驗
    我用PETS2009中的影象序列對多階編碼本模型進行了一些測試,測試結果還不錯,達到了預期的目標。測試環境為:CPU AMD閃龍3200 ,記憶體1.5G。處理768×576大小的影象大致需要150~200M記憶體。不過效能不夠好,更新背景模型大約需要300ms/幀,背景減除大約需要150ms/幀,更新的同時執行背景減除大約需要390ms/幀。如果使用C語言來實現多階編碼本模型,大約可以提高30%的效能;如果採用並行程式設計,每增加一個CPU大約又可以提高30%的效能。


個人見解
    這段時間看了不少關於背景建模及前景檢測方面的資料,並動手實踐了固定攝像機的多種方法,而運動攝像機的情況沒有涉及。為了適應更復雜的場景,背景模型越來越複雜;複雜的背景模型需要更多的記憶體和更大的計算量,相應的需要更加強勁的硬體。然而真的需要這麼複雜的背景模型嗎?我看未必,我傾向於選擇剛好夠用的背景模型,用牛刀去殺雞是得不償失的做法。

 

改進

    今天早上在刷牙的時候突然想到,現在的多階編碼本模型能夠做得更好:
(1)資料結構上,其實每個碼元中的權重不需要每次都去計算再儲存,只需在比較權重之前,計算權重閥值跟畫素總幀數的乘積weight’,然後用weight’與每個碼元的幀數去比較,效果也一樣。這樣做的好處有:減小了模型的記憶體佔用量,三通道影象中每個碼元佔用的位元組數從28減少到24;在更新模型時不必計算權重,可以為每個碼元減少一次乘法運算,減少一次迴圈。
(2)演算法能夠優化,例如使用一維陣列替代二維陣列就能在大迴圈中節約數十毫秒級的時間。