OpenCV中Grabcut算法的具體使用
Grabcut 算法主要運用於計算機視覺中的前背景分割,立體視覺和摳圖等。該算法利用瞭圖像中的紋理(顏色)信息和邊界(反差)信息,隻要少量的用戶交互操作即可得到比較好的分割結果.
1. Grabcut 的目標和背景的模型是RGB三通道的混合高斯模型GMM;
2. Grab Cut為一個不斷進行分割估計和模型參數學習的交互迭代過程;
3. Grab Cut隻需要提供背景區域的像素集就可以瞭。也就是說你隻需要框選目標,那麼在方框外的像素全部當成背景,這時候就可以對GMM進行建模和完成良好的分割瞭。即Grab Cut允許不完全的標註.
Grabcut 算法的基本步驟:
Grabcut的相關API:
void grabCut( InputArray img, //輸入圖像,必須是8位3通道圖像,在處理過程中不會被修改 InputOutputArray mask, //掩碼圖像,用來確定哪些區域是背景,前景,可能是背景, 可能是前景等 //mask既可以作為輸入也可以作為輸出。作為輸入時,mode要 選擇GC_INIT_WITH_MASK (=1); GCD_BGD (=0), 背景;GCD_FGD (=1),前景;GCD_PR_BGD (=2),可能是背景;GCD_PR_FGD(=3),可能是前景 Rect rect, //包含前景的矩形,格式為(x, y, w, h) InputOutputArray bgdModel,//算法內部使用的數組,隻需要創建大小為(1,65), 數據類型為np.float64的數組 InputOutputArray fgdModel,//同上 int iterCount, //算法迭代的次數 int mode = GC_EVAL //用來指示grabCut函數進行什麼操作 // GC_INIT_WITH_RECT (=0),用矩形窗初始化GrabCut; // GC_INIT_WITH_MASK (=1),用掩碼圖像初始化GrabCut );
有關鼠標操作的兩個函數:
void setMouseCallback( const string& winname, //圖像視窗名稱 MouseCallback onMouse, //鼠標響應函數,監視到鼠標操作後調用並處理相 應動作 void* userdata = 0 //鼠標響應處理函數的ID,識別號 );
void OnMouseAction( int event, // 代表瞭鼠標的各種操作 int x, // 代表鼠標位於窗口的(x,y)坐標位置,即Point(x,y) int y, int flags, // 代表鼠標的拖拽事件,以及鍵盤鼠標聯合事件 void *ustc // 標識瞭所響應的事件函數 );
int event: #define CV_EVENT_MOUSEMOVE 0 //滑動 #define CV_EVENT_LBUTTONDOWN 1 //左鍵點擊 #define CV_EVENT_RBUTTONDOWN 2 //右鍵點擊 #define CV_EVENT_MBUTTONDOWN 3 //中鍵點擊 #define CV_EVENT_LBUTTONUP 4 //左鍵放開 #define CV_EVENT_RBUTTONUP 5 //右鍵放開 #define CV_EVENT_MBUTTONUP 6 //中鍵放開 #define CV_EVENT_LBUTTONDBLCLK 7 //左鍵雙擊 #define CV_EVENT_RBUTTONDBLCLK 8 //右鍵雙擊 #define CV_EVENT_MBUTTONDBLCLK 9 //中鍵雙擊
int flags: #define CV_EVENT_FLAG_LBUTTON 1 //左鍵拖曳 #define CV_EVENT_FLAG_RBUTTON 2 //右鍵拖曳 #define CV_EVENT_FLAG_MBUTTON 4 //中鍵拖曳 #define CV_EVENT_FLAG_CTRLKEY 8 //(8~15)按Ctrl不放事件 #define CV_EVENT_FLAG_SHIFTKEY 16 //(16~31)按Shift不放事件 #define CV_EVENT_FLAG_ALTKEY 32 //(32~39)按Alt不放事件
Grabcut 算法的代碼示例:
#include<opencv2\highgui\highgui.hpp> #include<opencv2\imgproc\imgproc.hpp> #include<iostream> #include <opencv2\opencv.hpp> #include <math.h> using namespace cv; using namespace std; //grabcut算法 bool setMouse = false; //判斷鼠標左鍵的狀態(up / down) bool init; Point pt; Rect rect; Mat srcImg, mask, bgModel, fgModel; int numRun = 0; void onMouse(int, int, int, int, void*); void runGrabCut(); void showImage(); int main() { srcImg = imread("tahiti.jpg"); if (srcImg.empty()) { printf("could not load image...\n"); return -1; } imshow("源圖像", srcImg); mask.create(srcImg.size(), CV_8U); setMouseCallback("源圖像", onMouse, 0); while (1) { char c = (char)waitKey(0); if (c == ' ') {//選中矩形框後,按空格鍵執行grabcut分割 runGrabCut(); numRun++; showImage(); printf("current iteative times : %d\n", numRun); } if ((int)c == 27) { break; } } return 0; } void showImage() { Mat result, binmask; binmask = mask & 1; //進一步掩膜 if (init) //進一步摳出無效區域。鼠標按下,init變為false { srcImg.copyTo(result, binmask); } else { result = srcImg.clone(); } rectangle(result, rect, Scalar(0, 0, 255), 2, 8); imshow("源圖像", result); } void onMouse(int events, int x, int y, int flag, void *) { if (x < 0 || y < 0 || x > srcImg.cols || y > srcImg.rows) //無效區域 return; if (events == EVENT_LBUTTONDOWN) { setMouse = true; pt.x = x; pt.y = y; init = false; } else if (events == EVENT_MOUSEMOVE)//鼠標隻要動,就執行一次 { if (setMouse == true) //鼠標左鍵按住,滑動 { Point pt1; pt1.x = x; pt1.y = y; rect = Rect(pt, pt1);//定義矩形區域 showImage(); mask.setTo(Scalar::all(GC_BGD));//背景 mask(rect).setTo(Scalar(GC_PR_FGD));//前景 //對rect內部設置為可能的前景,外部設置為背景 } } else if (events == EVENT_LBUTTONUP) setMouse = false; //鼠標左鍵抬起 } void runGrabCut() { if (init)//鼠標按下,init變為false grabCut(srcImg, mask, rect, bgModel, fgModel, 1);//第二次迭代,用mask初始化grabcut else { grabCut(srcImg, mask, rect, bgModel, fgModel, 1, GC_INIT_WITH_RECT);//用矩形窗初始化GrabCut init = true; } }
到此這篇關於OpenCV中Grabcut算法的具體使用的文章就介紹到這瞭,更多相關OpenCV Grabcut算法內容請搜索WalkonNet以前的文章或繼續瀏覽下面的相關文章希望大傢以後多多支持WalkonNet!
推薦閱讀:
- OpenCV使用GrabCut實現摳圖功能
- C++ opencv利用grabCut算法實現摳圖示例
- OpenCV學習之圖像的分割與修復詳解
- C++ opencv實現在圖片上畫一條線示例代碼
- OpenCV繪制圓端矩形的示例代碼