OpenCV學習 20 grabcut分割演算法

2021-09-06 12:06:34 字數 3469 閱讀 8034

在opencv中,實現了grabcut分割演算法,該演算法可以方便的分割出前景影象,操作簡單,而且分割的效果很好。演算法的原理參見papaer:「grabcut」 — interactive foreground extraction using iterated graph cuts

比如下面的一副圖,我們只要選定乙個四邊形框,把框中的影象作為grabcut的乙個輸入引數,表示該框中的畫素可能屬於前景,但框外的部分一定屬於背景。

然後呼叫grabcut函式,就可以分割出城堡來。具體**如下:

// 矩形外的畫素是背景

cv::rect rectangle(50,70,image.cols-150,image.rows-180);

cv::mat result;

//兩個臨時矩陣變數,作為演算法的中間變數使用,不用care

cv::mat bgmodel,fgmodel;

double tt = cv::gettickcount();

// grabcut 分段

cv::grabcut(image, //輸入影象

result, //分段結果

rectangle,// 包含前景的矩形

bgmodel,fgmodel, // 前景、背景

1, // 迭代次數

cv::gc_init_with_rect); // 用矩形

//比較函式保留值為gc_pr_fgd的畫素

cv::compare(result,cv::gc_pr_fgd,result,cv::cmp_eq);

// 產生輸出影象

cv::mat foreground(image.size(),cv_8uc3,cv::scalar(255,255,255));

//背景值為 gc_bgd=0,作為掩碼

image.copyto(foreground,result);

grabcut函式的第乙個引數為我們要處理的影象,本程式中就是image,影象的型別必須為:cv_8uc3

第二個引數是mask影象,它的大小和image一樣,但是它的格式為cv_8uc1,只能是單通道的,grabcut演算法的結果就儲存在該影象中。

前面的**中,我們並沒有對mask影象(result)進行初始化設定,因為第6個引數為cv::gc_init_with_rect,它表示演算法會根據rectangle的範圍,來生成乙個初始化的mask影象。

cv::grabcut(image,    //輸入影象

result,   //分段結果

rectangle, // 包含前景的矩形

bgmodel,fgmodel, // 前景、背景

1,        // 迭代次數

cv::gc_init_with_rect); // 用矩形

mask影象的值只能為下面下面4個值(pr,probably表示可能的):

gc_bgd    = 0,  //背景

gc_fgd    = 1,  //前景

gc_pr_bgd = 2,  //可能背景

gc_pr_fgd = 3   //可能前景

根據rectangle生成的mask影象規則為:四邊形外面的部分一定是背景,所以在mask圖中對應的畫素值為gc_bgd,而四邊形內部的的值可能為前景,所以對應的畫素值為gc_pr_fgd。所以我們程式中使用mask影象應該如下圖所示。

如果第7個引數為gc_init_with_mask,這時第三個引數rectangle沒有使用,我們必須在呼叫grabcut函式之前,手工設定mask影象(變數result),如果我們把result設定成上圖所示的灰度圖。那個呼叫函式

cv::grabcut(image1,    //輸入影象

result1,   //分段結果

rectangle, // 包含前景的矩形

bgmodel,fgmodel, // 前景、背景

1,        // 迭代次數

cv::gc_init_with_mask); // 用矩形

可以得到同樣的結果。

cv::mat result1= cv::mat(image1.rows, image1.cols,cv_8uc1, cv::scalar(cv::gc_bgd));

//注意給子矩陣賦值的方法

cv::mat roi(result1, cv::rect(50,70,result1.cols-150,result.rows-180));

roi = cv::scalar(cv::gc_pr_fgd);

tt = cv::gettickcount();

// grabcut 分段

cv::grabcut(image1, //輸入影象

result1, //分段結果

rectangle,// 包含前景的矩形

bgmodel,fgmodel, // 前景、背景

1, // 迭代次數

cv::gc_init_with_mask); // 用矩形

//比較函式保留值為gc_pr_fgd的畫素

cv::compare(result1,cv::gc_pr_fgd,result,cv::cmp_eq);

// 產生輸出影象

cv::mat foreground1(image1.size(),cv_8uc3,cv::scalar(255,255,255));

//背景值為 gc_bgd=0,作為掩碼

image.copyto(foreground1,result1);

第3個引數是rectangle的大小位置,如果第7個引數為gc_init_with_mask,則該引數沒有作用。

第4,5個引數是兩個演算法在執行過程中使用臨時矩陣變數,不用care它們的內容。

第6個引數是迭代次數,迭代越多,效果越好,但劃時間也越長。

第7個引數是操作模式,通常情況下為gc_init_with_rect和gc_init_with_mask。

從上面的圖中,我們可以看到,grabcut演算法的效果很好,但是花的時間也很長,上面影象在我的筆記本上需要4.4秒。

程式源**:工程firstopencv13

OpenCV學習記錄20

一 學習內容 1.霍夫變換 直線檢測 1.1 在canny邊緣檢測基礎上,進行霍夫變換直線檢測 二 除錯 include include include using namespace cv using namespace std int main namedwindow figure1 cv wi...

如何安裝OpenCV2 0

2.開啟cmd,先進入opencv2.0的安裝目錄,本人的opencv2.0安裝在d program files opencv2.0 因此,cd d program files opencv2.0 3.在cmd中輸入 cmake g visual studio 9 2008 注意 的左右兩邊都有空格...

《學習OpenCV》 初探OpenCV(三)

引數1 影象 引數2 矩形的乙個頂點 引數3 矩形另乙個頂點 引數4 線條顏色 rgb 或亮度 灰度影象 可省略 有過載函式 引數5 線條粗細程度,取cv filled表填充色彩矩陣 引數6 線條型別 引數7 座標點的小數 cvmat cvcreatemat int rows,int cols,in...