基于Grab Cut交互性图像分割

本文深入探讨GrabCut图像分割技术,这是一种基于GraphCut的改进算法,通过迭代预测估计和不完全标记,允许用户仅需少量交互即可实现精确的图像分割。文章详细介绍了GrabCut的原理,展示了其在复杂背景中提取目标图像的应用,并提供了源代码示例。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

引言

Grab Cut是在Graph Cut上进行改进的,相比后者,前者的新颖之处在于:

  1. 迭代预测估计(iterative estimation)
  2. 不完全标记(incomplete labelling)

用户可以通过较少的交互性标记,就可以完成图像分割。具体的原理参考以下文章:

文中提到的经典论文:

  1. Interactive Graph Cutsfor Optimal Boundary & Region Segmentation of Objects in N-D Images  (Yuri Y. Boykov Marie-Pierre Jolly)
  2. “GrabCut” — Interactive Foreground Extraction using Iterated Graph Cuts  (Carsten Rother     Vladimir Kolmogorov
    Andrew Blake)

代码

最近在看图像分割方面的论文,发现了这种分割方法,这里复现了《“GrabCut” — Interactive Foreground Extraction using Iterated Graph Cuts》中的图像分割。只需要用鼠标将目标框出,可以将目标图像从复杂背景中“扣”出来。

// ConvertColor.cpp : 定义控制台应用程序的入口点。
//

#include <iostream>
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/imgproc/imgproc.hpp>


using namespace std;
using namespace cv;
// Global variables
// Flags updated according to left mouse button activity
bool ldown = false, lup = false;
// Original image
Mat img;
// Starting and ending points of the user's selection
Point corner1, corner2;
// ROI
Rect box;
Mat bgModel, fgModel, mask;
// Callback function for mouse events
static void mouse_callback(int event, int x, int y, int, void *)
{
	// When the left mouse button is pressed, record its position and save it in corner1
	if (event == EVENT_LBUTTONDOWN)
	{
		ldown = true;
		corner1.x = x;
		corner1.y = y;
		cout << "Corner 1 recorded at " << corner1 << endl;
	}
	// When the left mouse button is released, record its position and save it in corner2
	if (event == EVENT_LBUTTONUP)
	{
		// Also check if user selection is bigger than 20 pixels (jut for fun!)
		if (abs(x - corner1.x) > 10 && abs(y - corner1.y) > 10)
		{
			lup = true;
			ldown = false;
			corner2.x = x;
			corner2.y = y;
			cout << "Corner 2 recorded at " << corner2 << endl << endl;
		}
		else
		{
			cout << "Please select a bigger region" << endl;
			ldown = false;
		}
	}
	// Update the box showing the selected region as the user drags the mouse
	if (ldown == true && lup == false)
	{
		Point pt;
		pt.x = x;
		pt.y = y;
		Mat local_img = img.clone();
		rectangle(local_img, corner1, pt, Scalar(0, 0, 255),3);
		imshow("Cropping app", local_img);
	}
	// Define ROI and crop it out when both corners have been selected
	if (ldown == false && lup == true)
	{
		box.width = abs(corner1.x - corner2.x);
		box.height = abs(corner1.y - corner2.y);
		box.x = min(corner1.x, corner2.x);
		box.y = min(corner1.y, corner2.y);
		// Make an image out of just the selected ROI and display it in a new window
	/*	Mat crop(img, box);*/
		grabCut(img, mask, box, bgModel, fgModel, 5, cv::GC_INIT_WITH_RECT);
		compare(mask, GC_PR_FGD, mask, cv::CMP_EQ);
		namedWindow("Crop");
		Mat imageROI;
		imageROI.create(img.size(), img.type());
		/*imageROI = img(Rect(box));*/
		imageROI.setTo(Scalar(255, 255, 255));
		img.copyTo(imageROI, mask);
		Mat crop(imageROI, box);
		imshow("Crop", crop);
		//Mat test = img - imageROI;
		//imshow("Crop", test);
		///*imwrite("Crop1.jpg", imageROI);*/
		ldown = false;
		lup = false;
	}
}
int main()
{
	img = imread("flower.jpg");
	/*img = imread("Crop.jpg");*/
	namedWindow("Cropping app");
	imshow("Cropping app", img);
	// Set the mouse event callback function
	setMouseCallback("Cropping app", mouse_callback);
	// Exit by pressing 'q'
	while (char(waitKey(1)) != 'q') {}
	return 0;
}

结果

从下图看,效果还算可以!

感谢阅读,请多指教!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值