OpenCV中Grabcut算法的具體使用
Grabcut 算法主要運用于計算機視覺中的前背景分割,立體視覺和摳圖等。該算法利用了圖像中的紋理(顏色)信息和邊界(反差)信息,只要少量的用戶交互操作即可得到比較好的分割結果.
1. Grabcut 的目標和背景的模型是RGB三通道的混合高斯模型GMM;
2. Grab Cut為一個不斷進行分割估計和模型參數(shù)學習的交互迭代過程;
3. Grab Cut只需要提供背景區(qū)域的像素集就可以了。也就是說你只需要框選目標,那么在方框外的像素全部當成背景,這時候就可以對GMM進行建模和完成良好的分割了。即Grab Cut允許不完全的標注.
Grabcut 算法的基本步驟:

Grabcut的相關API:

void grabCut( InputArray img, //輸入圖像,必須是8位3通道圖像,在處理過程中不會被修改
InputOutputArray mask, //掩碼圖像,用來確定哪些區(qū)域是背景,前景,可能是背景,
可能是前景等
//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,//算法內部使用的數(shù)組,只需要創(chuàng)建大小為(1,65),
數(shù)據(jù)類型為np.float64的數(shù)組
InputOutputArray fgdModel,//同上
int iterCount, //算法迭代的次數(shù)
int mode = GC_EVAL //用來指示grabCut函數(shù)進行什么操作
// GC_INIT_WITH_RECT (=0),用矩形窗初始化GrabCut;
// GC_INIT_WITH_MASK (=1),用掩碼圖像初始化GrabCut
);有關鼠標操作的兩個函數(shù):
void setMouseCallback( const string& winname, //圖像視窗名稱
MouseCallback onMouse, //鼠標響應函數(shù),監(jiān)視到鼠標操作后調用并處理相
應動作
void* userdata = 0 //鼠標響應處理函數(shù)的ID,識別號
);void OnMouseAction( int event, // 代表了鼠標的各種操作
int x, // 代表鼠標位于窗口的(x,y)坐標位置,即Point(x,y)
int y,
int flags, // 代表鼠標的拖拽事件,以及鍵盤鼠標聯(lián)合事件
void *ustc // 標識了所響應的事件函數(shù)
);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; //判斷鼠標左鍵的狀態(tài)(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 == ' ') {//選中矩形框后,按空格鍵執(zhí)行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) //進一步摳出無效區(qū)域。鼠標按下,init變?yōu)閒alse
{
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) //無效區(qū)域
return;
if (events == EVENT_LBUTTONDOWN)
{
setMouse = true;
pt.x = x;
pt.y = y;
init = false;
}
else if (events == EVENT_MOUSEMOVE)//鼠標只要動,就執(zhí)行一次
{
if (setMouse == true) //鼠標左鍵按住,滑動
{
Point pt1;
pt1.x = x;
pt1.y = y;
rect = Rect(pt, pt1);//定義矩形區(qū)域
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變?yōu)閒alse
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算法內容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!

