天天看點

opencv Grabcut-摳圖

Grabcut原理見:https://blog.csdn.net/zouxy09/article/details/8534954

grabCut() 函數

cv::grabCut(image,    //輸入圖像 
    result,   //分段結果 
    rectangle, // 包含前景的矩形 
    bgModel,fgModel, // 前景、背景 
    1,        // 疊代次數 
    cv::GC_INIT_WITH_RECT); // 用矩形 
           
#include <opencv2/opencv.hpp>
#include <iostream>
using namespace cv;
using namespace std;

const char* winTitle = "input image";
Rect rect;
Mat src, image, mask, bgMode, fgMode;
int numRun = 0;
bool init = false;

void runGrabcut()
{
	if (rect.width < 2 || rect.height < 2)
		return;
	if (init)
		grabCut(src, mask, rect, bgMode, fgMode, 1); // 完成第一次的初始化之後,就不需要用矩形了,直接用model了。
	else
	{
		grabCut(src, mask, rect, bgMode, fgMode, 1, GC_INIT_WITH_RECT);
		init = true;
	}
}

void setROIMask()
{
	mask.setTo(Scalar(GC_BGD));
	rect.x = max(0, rect.x);
	rect.y = max(0, rect.y);
	rect.width = min(rect.width, src.cols - rect.x);
	rect.height = min(rect.height, src.rows - rect.y);

	mask(rect).setTo(Scalar(GC_PR_FGD));
}

void showImage()
{
	Mat result, binMask;
	binMask.create(mask.size(), CV_8UC1);
	binMask = mask & 1;
	if (init)
		src.copyTo(result, binMask);
	else
		src.copyTo(result);
	
	rectangle(result, rect, Scalar(0, 0, 255), 2, 8);
	imshow(winTitle, result);
}

void onMouse(int event, int x, int y, int flags, void* param)
{
	switch (event)
	{
	case EVENT_LBUTTONDOWN:
		rect.x = x;
		rect.y = y;
		rect.width = 1;
		rect.height = 1;

		init = false;
		numRun = 0;
		break;

	case EVENT_MOUSEMOVE: 
		if (flags * EVENT_FLAG_LBUTTON)// 左鍵按住
		{
			rect = Rect(Point(rect.x, rect.y), Point(x, y));
			showImage();
		}
		break;

	case EVENT_LBUTTONUP:
		if (rect.width > 1 && rect.height > 1)
		{
			setROIMask();
			showImage();
		}
		break;

	default:
		break;
	}
}

int main()
{
	src = imread("D:/source/images/flower3.png");
	if (src.empty())
	{
		puts("read image empty");
		system("pause");
		return -1;
	}
	mask.create(src.size(), CV_8UC1);
	mask.setTo(Scalar::all(GC_BGD));

	namedWindow(winTitle, CV_WINDOW_AUTOSIZE);
	setMouseCallback(winTitle, onMouse);

	imshow(winTitle, src);

	while (true)
	{
		char c = (char)waitKey(0);
		if (c == 27) break;
		if (c == 'n')
		{
			numRun++;
			runGrabcut();
			showImage();
			printf("numRun = %d\n", numRun);
		}
	}
	return 0;
}
           
opencv Grabcut-摳圖

将花扣出來後的效果:

opencv Grabcut-摳圖