OpenCV之图像分割(四) Grabcut抠图

并没有深入的对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;
	}
}

效果图:

  • 2
    点赞
  • 32
    收藏
    觉得还不错? 一键收藏
  • 10
    评论
评论 10
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值