Grabcut图像分割(背景替换)__opencv_day-119

Grabcut图像分割

Grabcut是基于图像切割(graph cut)实现的图像切割算法,它需要用户输入一个bounding box作为分割目标位置,实现对目标与背景的分割或分离,这个跟Kmeans与MeanShift等图像分割方法有很大的不同,但是Gradcut分割速度快,效果很好,支持交互操作,因此在很多app图像分割、背景虚化的软件中可以看到它的身影。
void cv::grabCut(
InputArray img,
InputOutputArray mask,
Rect rect,
InputOutputArray bgdModel,
InputOutputArray fgdModel,
int iterCount,
int mode = GC_EVAL
)
img 输入的三通道图像
mask 输入的单通道图像,初始化方式为GC_INIT_WITH_RECT表示ROI区域可以被初始化为:

  • GC_BGD 定义为明显的背景像素 0
  • GC_FGD 定义为明显的前景像素 1
  • GC_PR_BGD 定义为可能的背景像素 2
  • GC_PR_FGD 定义为可能的前景像素 3
  • rect 表示roi区域
  • bgdModel表示临时背景模型数组
  • fgdModel表示临时前景模型数组
  • iterCount表示图割算法迭代次数
  • mode当使用用户提供的roi时候使用GC_INIT_WITH_RECT
Grabcut图像分割 – 背景替换

使用Grabcut实现图像对象提取,通过背景图像替换,实现图像合成,通过对背景图像高斯模糊实现背景虚化效果,完整的步骤如下:

  1. ROI区域选择
  2. Grabcut对象分割
  3. Mask生成
  4. 使用mask,实现背景与前景的高斯权重融合
例子;
#include 
#include 
#include 
#include 


using namespace cv;
using namespace std;

int main(int argc, char** argv) {

	//读取图像
	Mat src = imread("E:/opencv/master.jpg");
	Mat background = imread("E:/opencv/beijing1.jpg");
	
	if (src.empty() || background.empty()) {
		cout << "没有找到图片" << endl;
		return -1;
	}

	
	imshow("src", src);
	imshow("background", background);

	//创建单通道的mask
	Mat mask;
	Rect rect(53, 12, src.cols - 100, src.rows - 12);

	Mat bgdModel, fgdModel;
	grabCut(src, mask, rect, bgdModel, fgdModel, 5, GC_INIT_WITH_RECT);

	//比较
	compare(mask, GC_PR_FGD, mask, CMP_EQ);
	
	
	Mat element = getStructuringElement(MORPH_RECT, Size(3, 3));

	//膨胀
	dilate(mask, mask, element);

	//高斯模糊
	GaussianBlur(mask, mask, Size(5, 5), 0);
	imshow("background-mask", mask);

	//虚化背景
	GaussianBlur(background, background, Size(0, 0), 15);

	//混合图像
	Mat result = Mat::zeros(src.size(), src.type());
	for (int i = 0; i < src.rows; i++) {
		for (int j = 0; j < src.cols; j++) {
			float w1 = mask.at(i, j) / 255.0;
			int b = src.at(i, j)[0];
			int g = src.at(i, j)[1];
			int r = src.at(i, j)[2];
			int b1 = background.at(i, j)[0];
			int g1 = background.at(i, j)[1];
			int r1 = background.at(i, j)[2];
			int b3 = (1.0 - w1) * b1 + b * w1;
			int g3 = (1.0 - w1) * g1 + g * w1;
			int r3 = (1.0 - w1) * r1 + r * w1;
			result.at(i, j)[0] = static_cast(b3);
			result.at(i, j)[1] = static_cast(g3);;
			result.at(i, j)[2] = static_cast(r3);;

		}
	}


	imshow("result", result);
	waitKey(0);
	return 0;
}

你可能感兴趣的:(图像处理)