【OpenCV學習筆記 023】兩種圖像分割方法比較
此次研究兩種圖像分割法,分别是基于形态學的分水嶺算法和基于圖割理論的GrabCut算法。OpenCV均提供了兩張算法或其變種。鑒于研究所需,記錄一些知識點,開發平台為OpenCV2.4.9+Qt5.3.2。
一、使用分水嶺算法進行圖像分割
分水嶺變換是一種常用的圖像處理算法,在網上很容易搜到詳細的原理分析。簡單來說,這是一種基于拓撲理論的數學形态學的圖像分割方法,其基本思想是把圖像看作是測地學上的拓撲地貌,圖像中每一點像素的灰階值表示該點的海拔高度,每一個局部極小值及其影響區域稱為集水盆,而集水盆的邊界則形成分水嶺。分水嶺的概念和形成可以通過模拟浸入過程來說明。在每一個局部極小值表面,刺穿一個小孔,然後把整個模型慢慢浸入水中,随着浸入的加深,每一個局部極小值的影響域慢慢向外擴充,在兩個集水盆彙合處構築大壩,即形成分水嶺。
分水嶺算法簡單,是以存在一些缺陷,如容易導緻圖像的過度分割。分水嶺算法對微弱邊緣具有良好的響應,圖像中的噪聲、物體表面細微的灰階變化,都會産生過度分割的現象。
為消除分水嶺算法産生的過度分割,有兩種正常的處理方法,一是利用先驗知識去除無關邊緣資訊。二是修改梯度函數使得集水盆隻響應想要探測的目标。
OpenCV提供了該算法的改進版本,使用預定義的一組标記來引導對圖像的分割,該算法是通過cv::watershed函數來實作的。
要實作分水嶺算法,首先建立一個類WaterShedSegmentation,在watershedsegmentation.h中添加:
接着,在watershedsegmentation.cpp中添加:
main函數修改如下:
效果1:算法識别出屬于前景和背景的像素(有誤差)。
效果2:組合前景和背景圖,形成标記圖形,這是分水嶺的輸入參數。
效果3:分割結果中,标記圖像得到更新。
效果4:顯示邊界圖像。
可以看出,分水嶺算法對微弱邊緣具有良好的響應,是得到封閉連續邊緣的保證的。但對于不同品質的圖像其分割效果不盡相同,但總的來說效果仍需要改進。
二、使用GrabCut算法分割圖像
GrabCut是另一種同樣較為流行的圖像分割算法。GrabCut是在GraphCut基礎上改進的一種圖像分割算法,它并非基于圖像形态學,而是基于圖割理論(參考:http://www.cnblogs.com/tornadomeet/archive/2012/11/06/2757585.html)。在使用GrabCut時,需要人工給定一定區域的目标或者背景,然後算法根據設定的參數來進行分割。GrabCut在計算時比分水嶺算法更加複雜,尤其适合從靜态圖像中提取前景照片的應用。
OpenCV中提供了cv::grabcut函數,是以隻需提供圖像并标記背景像素和前景像素,基于局部的标記,算法即可将圖像中的像素進行分割。在這裡使用的局部标記方法是定義一個矩形。cv::grabcut的函數定義如下:
在main函數添加:
效果:
在函數cv::grabCut中,最後一個參數表示我們使用的是包圍盒模式,而該算法支援的輸入/輸出分割圖像可以有四種數值,如函數cv::compare函數中的參數:
cv::GC_BGD:确定屬于背景的像素;
cv::GC_FGD:确定屬于前景的元素;
cv::GC_PR_BGD:可能屬于背景的元素;
cv::GC_PR_FGD:可能屬于前景的元素。
在上圖中,GrabCut算法通過指定方框區域來提取前景物體。同時,也可将數值cv::GC_BGD和cv::GC_FGD賦予分割圖像的某些特定像素,并且把這類分割圖像作為cv::grabcut函數的第二個參數(此時需要指定GC_INIT_WITH_MASK作為輸入模式)。
基于這些資訊,GrabCut通過以下主要步驟建立分割:
前景标簽(cv::GC_PR_FGD)被臨時賦予所有為标記的像素。基于目前的分類,算法将像素歸類為顔色或灰階值相似的聚類。
通過引入背景與前景像素的邊界進行分割。這個優化的過程嘗試将标簽相似的像素相連接配接,這裡利用了在強度相對已知的區域之間對邊界像素的(懲罰?)。這個最優化問題通過GraphCut算法得到高效解決。
對擷取的分割結果産生新的像素标簽,重複聚類過程,找到新的最優解。根據場景的複雜度,得到最佳結果,對于簡單的場景,有時隻需要一次疊代。
關于GrabCut算法,還需要進一步研究GraphCut才能深刻了解。