1. 程式人生 > >藉助影象直方圖來檢測特定物(MeanShift、CamShift演算法) 很詳細

藉助影象直方圖來檢測特定物(MeanShift、CamShift演算法) 很詳細

直方圖是一個簡單的表,它給出了一幅影象或一組影象中擁有給定數值的畫素數量。因此,灰度影象的直方圖有256個條目(或稱為容器)。0號容器給出值為0的畫素數目,1號容器給出值為1的畫素個數,以此類推。

直方圖反投影

直方圖是影象內容的一個重要特性。如果一幅影象的區域中顯示的是一種獨特的紋理或是一個獨特的物體,那麼這個區域的直方圖可以看做一個概率函式,它給出的是某個畫素屬於該紋理或物體的概率。這使得我們可以藉助影象的直方圖來檢測特定的內容。
反投影直方圖的方法是一種把目標概率分佈對映到觀測影象的簡單方法。其作用是,替換一個輸入影象中每一個畫素值,使其變成感興趣區域(ROI)的直方圖中對應的概率值
其在opencv2的C++ API為:

cv::calcBackProject(&image,                 1,                //一幅影象     channels,        //通道數量     histogram,        //進行反投影的直方圖     result,            //生成的反投影影象     ranges,            //每個維度的值域     255.0              //縮放因子     );

HSV顏色空間

HSV(Hue,Saturation,Value)是根據顏色的直觀特性(色調H,飽和度S,亮度V)建立的一種顏色空間, 也稱六角錐體模型(Hexcone Model)。

色調H

用角度度量,取值範圍為0°~360°,從紅色開始按逆時針方向計算,紅色為0°,綠色為120°,藍色為240°。它們的補色是:黃色為60°,青色為180°,品紅為300°;

飽和度S

取值範圍為0.0~1.0,值越大,顏色越飽和。

亮度V

取值範圍為0.0(黑色)~1.0(白色)。
HSV模型的三維表示從RGB立方體演化而來。設想從RGB沿立方體對角線的白色頂點向黑色頂點觀察,就可以看到立方體的六邊形外形。六邊形邊界表示色彩,水平軸表示純度,明度沿垂直軸測量。

HSV顏色空間

HSV顏色空間

hue表示顏色的相位角,取值範圍是0---360;S表示顏色的飽和度;S為一比例值,範圍從0到1,它表示成所選顏色的純度和該顏色最大的純度之間的比率,通俗點講,S表示的是某種顏色的“純度”, S取值越大,表示色彩越純,取值越小,表示色彩越灰。V表示色彩的明亮程度,範圍從0到1。V等於0表示圓錐的底部定點,也就是黑色,V等於1表示圓錐的頂面,當V=1並且S=0時表示純白色。

HSV圓錐

HSV圓錐

應用示例:建立顏色概率模型

由於我們要進行的是通過一種演算法來實現檢測特定物體(尤其是人臉)的功能,所以通過這個示例的引入,來為後面介紹Mean Shift演算法打下基礎。
因為膚色在顏色空間的分析相當集中,但會受到光照和人種的影響。為了減少膚色收光照強度的影響,通常將顏色空間從RBG轉換到亮度和色度分離的某個顏色空間,如HSV顏色空間,然後放棄亮度分量。
採集膚色樣本,吧膚色樣本中的每個畫素從RGB空間轉換到HSV空間,統計其H分量的直方圖,並對該直方圖進行歸一化處理,就可以得到膚色在H空間的概率分佈,該概率分佈就是所需的跟蹤模式。

具體步驟如下:
1、將觀測影象中每個畫素從RGB空間對映到HSV空間,按公式計算H分量大小建立起統計直方圖
2、根據直方圖進行反向投影運算,即,將觀測影象中的每個畫素值,用其H分量在已建立的統計直方圖中對應的值代替
3、所得到輸出影象就是觀測影象的顏色概率分佈圖像

現在,用程式演示直方圖反投影演算法中使用顏色資訊。

class ContentFinder { private:     float hranges[2];     const float* ranges[3];     int channels[3];     float threshold;     cv::MatND histogram;  public:     ContentFinder():threshold(-1.0f){         ranges[0] = hranges;//所有通道的值相同         ranges[1] = hranges;         ranges[2] = hranges;     }      //設定直方圖的閾值[0,1]     void setThreshold(float t)     {         threshold = t;     }      //獲取閾值     float getThreshold()     {         return threshold;     }      //設定參考直方圖     void setHistogram(const cv::MatND& h)     {         histogram = h;         cv::normalize(histogram,histogram,1.0);//輸入直方圖必須是歸一化後的     }      cv::Mat find(const cv::Mat& image,                 float minValue,float maxValue,                 int* channels,int dim);  };  cv::Mat ContentFinder::find(const cv::Mat& image,                             float minValue,float maxValue,                             int* channels,int dim) {     cv::Mat result;     hranges[0] = minValue;     hranges[1] = maxValue;      for(int i=0;i<dim;i++)     {         this->channels[i] = channels[i];     }     cv::calcBackProject(&image,1,    //輸入圖片                         channels,    //所有通道列表                         histogram,    //直方圖                         result,        //反投影的結果                         ranges,        //值域                         255.0        //縮放因子                         );     //進行閾值化以得到二值影象     if(threshold > 0.0)         cv::threshold(result,result,255*threshold,255,cv::THRESH_BINARY);     return result; }

均值漂移(Mean Shift)演算法

假設我們現在知道物體的近似位置,概率對映可用於找到的物件的確切位置。最有可能的位置是在已知視窗區域中得到最大概率的位置。因此,如果我們從最初的位置開始,並且迭代移動,邊可以找到精確的位置。這便是均值漂移演算法所要完成的任務。

原理

均值漂移演算法以迭代的方式鎖定概率函式的區域性最大值。它主要是尋找預定義視窗中資料點的重心點,或者說加權平均值。該演算法將視窗中心移動到資料點的重心處,並重復這個過程直到視窗重心收斂到一個穩定點。
從數學角度上說,Mean Shift演算法利用概率密度的梯度爬升來尋找區域性最優。當輸入一個影象的範圍,然後根據反向投影圖和輸入的方框進行Mean Shift迭代,它是向重心移動,即向反向投影圖中概率大的地方移動,所以始終會移動到目標上,Mean Shift演算法是一個變步長的梯度上升演算法
現考慮一個點集(這可以是經過直方圖反投影的畫素點的分佈),現有一個小視窗,需要將其移至畫素點最密集的區域。如下圖所示:

meanshift_basics

meanshift_basics

最初的視窗表示為C1這個大的藍色圓圈,其原始中心為"C1_o"。隨著這個中心點向區域性密度較大的區域移動,得到了"C1_r"的中心點。隨著這個過程的迭代,最終會得到一個最大畫素點分佈的區域,即C2,該區域包含了最多數量的點。

總結下來,Mean Shift的基本思路是,從每個畫素開始,首先估計有相似顏色的鄰近畫素點的密度(區域性密度)的梯度,而後利用迭代演算法求出區域性密度的峰值(即重心點),把能夠聚類到同一個峰值點的所有畫素點劃分成一個區域。

基本流程

(1)選擇跟蹤視窗的大小和初始位置。在Mean Shift跟蹤演算法中,核窗寬(即核函式的定義域的大小,就是搜尋視窗的大小)的大小起著非常重要的作用。因為它不但決定了參與Mean Shift迭代的樣本數量,而且也反映了跟蹤視窗的大小。通常,核窗寬由初始跟蹤視窗的尺寸決定,而且在整個跟蹤過程中不再發生變化。

meanshift_step1

meanshift_step1

(2)計算跟蹤視窗內的質心(或重心)。在離散二維(2D)概率分佈圖像中,計算某視窗的質心同物理上計算某物體的質心一樣,即利用視窗的零階矩M00和(x,y)的一階矩(M10,M01)之間的關係,計算得到視窗的質心。

公式

公式

meanshift_step2

meanshift_step2

(3)調整跟蹤視窗的中心到質心;
(4)重複第二步和第三步,直到跟蹤視窗中心和質心“會聚”,即每次視窗移動的距離小於一定的閾值。

meanshift_step3

meanshift_step3

一般一個影象就是個矩陣,畫素點均勻的分佈在影象上,就沒有點的稠密性。所以怎樣來定義點的概率密度,這才是最關鍵的。而我們可以根據畫素點的顏色相近來定義為概率密度高。
其作為人臉跟蹤的應用由下圖演示:

meanshift_face

meanshift_face

優點

Mean Shift作為一種高效的模式匹配演算法,由於不需要進行全域性搜尋,而且搜尋精度高,已經廣泛地應用在各種模式識別、實時可視跟蹤等領域。

不足

缺乏必要的模型更新方法;整個跟蹤過程中跟蹤視窗的大小保持不變,當目標存在尺度變化的時候會導致尺度定位不準確。

連續自適應的Meanshift(CamShift)演算法

Bradski根據Mean Shift演算法的不足,提出了Camshift演算法。CamShift演算法,即Continuously Adaptive Mean-Shift演算法,基本思想就是對視訊影象的多幀進行MeanShift運算,將上一幀結果作為下一幀的初始值,迭代下去。
該演算法採用不變矩對目標的尺寸進行估算,實現了連續自適應地調整跟蹤視窗的大小和位置,並將其應用在對連續彩色影象序列中的運動目標的快速跟蹤。
簡單點說,Mean Shift是針對單張圖片尋找最優迭代結果,而Camshift則是針對視訊序列來處理,並對該序列中的每一幀圖片都呼叫Mean Shift來尋找最優迭代結果。正是由於Camshift針對一個視訊序列進行處理,從而保證其可以不斷調整視窗的大小,如此一來,當目標的大小發生變化的時候,該演算法就可以自適應地調整目標區域繼續跟蹤。

原理

Camshift演算法首先根據跟蹤目標顏色概率模型,將視訊影象轉化為概率分佈圖像(PDI),並初始化一個矩形搜尋視窗,對每一幀PDI影象利用Mean Shift演算法搜尋目標匹配的最優區域,並根據搜尋區域的不變矩估算跟蹤目標的中心和大小,儲存和輸出當前幀搜尋結果,並且用當前幀搜尋結果作為下一幀影象初始化搜尋視窗。如此迴圈,即可實現對目標的連續跟蹤。Camshift演算法是一種動態變化的非引數密度函式梯度估計方法

具體步驟

(1)建立指定視窗的顏色概率分佈圖,初始化一個搜尋視窗W,其大小為S

camshift_1

camshift_1

由上圖左圖的直方圖可以知道,選定區域最常見的色度範圍。假設新的視訊幀到來時,每個畫素點的色度值被檢測,通過直方圖給出該畫素點的概率值。
(2)利用Mean Shift演算法使搜尋視窗“收斂";在2D概率分佈圖像中,計算搜尋視窗的質心;調整搜尋視窗的中心到計算的質心位置。重複該過程,直到“收斂”(即中心的位移小於給定的閾值)
(3)重新設定搜尋視窗的大小S並計算跟蹤目標的輸出引數,並用新的視窗大小初始化下一幀Mean Shift的搜尋視窗

camshift_2

camshift_2

上圖表示通過Camshift演算法跟蹤人臉時計算一個視訊幀影象中可能存在人臉的影象。黑色畫素概率值最低,白色畫素概率值最高,灰色畫素介於二者之間。
(4)跳轉到第二步進行下一幀的迴圈

下面是Camshift演算法的人臉跟蹤演示:

camshift_face

camshift_face

參考資料

OpenCV 3.0.0-dev documentation
OpenCV 2 計算機視覺程式設計手冊,科學出版社
基於OpenCV的人臉跟蹤識別系統研究,雷靜,西安電子科技大學,碩士學位論文,2010
Meanshift,聚類演算法