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

Grabcut的相關(guān)API:

void grabCut( InputArray img, //輸入圖像,必須是8位3通道圖像,在處理過程中不會(huì)被修改
InputOutputArray mask, //掩碼圖像,用來確定哪些區(qū)域是背景,前景,可能是背景,
可能是前景等
//mask既可以作為輸入也可以作為輸出。作為輸入時(shí),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,//算法內(nèi)部使用的數(shù)組,只需要?jiǎng)?chuàng)建大小為(1,65),
數(shù)據(jù)類型為np.float64的數(shù)組
InputOutputArray fgdModel,//同上
int iterCount, //算法迭代的次數(shù)
int mode = GC_EVAL //用來指示grabCut函數(shù)進(jìn)行什么操作
// GC_INIT_WITH_RECT (=0),用矩形窗初始化GrabCut;
// GC_INIT_WITH_MASK (=1),用掩碼圖像初始化GrabCut
);有關(guān)鼠標(biāo)操作的兩個(gè)函數(shù):
void setMouseCallback( const string& winname, //圖像視窗名稱
MouseCallback onMouse, //鼠標(biāo)響應(yīng)函數(shù),監(jiān)視到鼠標(biāo)操作后調(diào)用并處理相
應(yīng)動(dòng)作
void* userdata = 0 //鼠標(biāo)響應(yīng)處理函數(shù)的ID,識(shí)別號(hào)
);void OnMouseAction( int event, // 代表了鼠標(biāo)的各種操作
int x, // 代表鼠標(biāo)位于窗口的(x,y)坐標(biāo)位置,即Point(x,y)
int y,
int flags, // 代表鼠標(biāo)的拖拽事件,以及鍵盤鼠標(biāo)聯(lián)合事件
void *ustc // 標(biāo)識(shí)了所響應(yīng)的事件函數(shù)
);int event: #define CV_EVENT_MOUSEMOVE 0 //滑動(dòng) #define CV_EVENT_LBUTTONDOWN 1 //左鍵點(diǎn)擊 #define CV_EVENT_RBUTTONDOWN 2 //右鍵點(diǎn)擊 #define CV_EVENT_MBUTTONDOWN 3 //中鍵點(diǎn)擊 #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; //判斷鼠標(biāo)左鍵的狀態(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í)行g(shù)rabcut分割
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; //進(jìn)一步掩膜
if (init) //進(jìn)一步摳出無效區(qū)域。鼠標(biāo)按下,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)//鼠標(biāo)只要?jiǎng)?,就?zhí)行一次
{
if (setMouse == true) //鼠標(biāo)左鍵按住,滑動(dòng)
{
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內(nèi)部設(shè)置為可能的前景,外部設(shè)置為背景
}
}
else if (events == EVENT_LBUTTONUP)
setMouse = false; //鼠標(biāo)左鍵抬起
}
void runGrabCut()
{
if (init)//鼠標(biāo)按下,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;
}
}

到此這篇關(guān)于OpenCV中Grabcut算法的具體使用的文章就介紹到這了,更多相關(guān)OpenCV Grabcut算法內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
解決了個(gè)困擾了2天的問題,定點(diǎn)運(yùn)算問題
本文主要講解定點(diǎn)運(yùn)算問題,需要的朋友可以參考一下。2016-06-06
C語言實(shí)現(xiàn)父進(jìn)程主動(dòng)終止子進(jìn)程的方法總結(jié)
一般的情況,子進(jìn)程自己運(yùn)行完后,執(zhí)行exit 或者return 后,父進(jìn)程wait. waitpid收回子進(jìn)程,但子進(jìn)程是一個(gè)循環(huán)等待狀態(tài)不主動(dòng)退出,父進(jìn)程可以采用文中介紹的幾種方法,需要的朋友可以參考下2023-10-10
OpenCV實(shí)現(xiàn)車牌字符分割(C++)
這篇文章主要為大家詳細(xì)介紹了OpenCV實(shí)現(xiàn)車牌字符分割,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2020-11-11
C++實(shí)現(xiàn)水仙花數(shù)判斷實(shí)例
大家好,本篇文章主要講的是C++實(shí)現(xiàn)水仙花數(shù)判斷實(shí)例,感興趣的同學(xué)趕快來看一看吧,對你有幫助的話記得收藏一下,方便下次瀏覽2022-01-01

