并没有深入的对grabCut算法进行深入的研究,只是学会初步使用这个API
效果示意图:
工作流程:
代码:
#include <opencv2/opencv.hpp>
#include <iostream>
#include <math.h>
using namespace cv;
using namespace std;
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("timg.jpg");
if (srcImg.empty())
{
printf("could not load image...\n");
return -1;
}
namedWindow("【源图像】", 0);
imshow("【源图像】", srcImg);
mask.create(srcImg.size(), CV_8U);
setMouseCallback("【源图像】", onMouse, 0);
while (1)
{
char c = (char)waitKey(0);
if (c == 'n') {
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) //进一步抠出无效区域
{
srcImg.copyTo(result, binmask);
}
else
{
result = srcImg.clone();
}
rectangle(result, rect, Scalar(0, 0, 255),2,8);
imshow("【源图像】", result);
}
void setROIMask()
{
mask.setTo(Scalar::all(GC_BGD));
mask(rect).setTo(Scalar(GC_PR_FGD));
}
void onMouse(int events,int x,int y,int flag,void *param)
{
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();
setROIMask(); //对rect内部设置为可能的前景,外部设置为背景
}
}
else if (events == EVENT_LBUTTONUP)
setMouse = false; //鼠标左键抬起
}
void runGrabCut()
{
if (init)
grabCut(srcImg, mask, rect, bgModel, fgModel, 1);
else
{
grabCut(srcImg, mask, rect, bgModel, fgModel, 1, GC_INIT_WITH_RECT);
init = true;
}
}