Graphcut主要用于图像背景与前景的分割,是一种基于图论的分割方法,在计算机视觉领域中应用于前景分割、医学处理、纹理分割及立体视觉等方面,类似于PS中的抠图功能。基本图论的分割技术是图像分割领域中新的研究热点,该方法基于能量优化算法,将图像分割问题转换为图的最小割优化问题。
Grabcut是Graphcut算法的改进,Graphcut是一种直接基于图切算法的图像分割技术,仅仅需要确认前景与背景输入,该算法就可以完成背景与前景相似督导赋权图,并通过最优切割来实现图像分割。Grabcut算法可以不需要用户交互,仅仅需要输入包含目标前景的区域就可以完成前景与前景的分离。
Graphcut的目标和背景模型是灰度直方图,Grabcut采用的是RGB三通道混合高斯模型;Graphcut的能量最小化分割是能通过一次计算实现的,而Grabcut是根据分割模型参数更新完成学的学习过程;Graphcut需要用户输入前景与背景区域点集,而Grabcut只需要提供含有背景的区域像素集就可以完成分割。
上面三段话纯属装逼,实际上,只是对Grabcut算法和Graphcut算法大致的介绍,如果想了解详细原理,可以搜索公众号"qxsf321",回复0043后提供三篇文章给你看,让你能详细了解原理。
OpenCV中提供了Grabcut函数用于实现Grabcut操作,原型如下:
C++: void grabCut(InputArray img, InputOutputArray mask, Rect rect, InputOutputArray bgdModel, InputOutputArray fgdModel, int iterCount, int mode=GC_EVAL )
参数意义如下:
img:输入图像,要求是8-bit 3-channel 图像。
mask:输入/输出的掩码图。如果最后一个参数mode=GC_INIT_WITH_RECT,则掩码图像由函数自行初始化。这个掩码图元素可能的取值如下:
GC_BGD:表示明显的背景像素,宏义值为0;
GC_FGD:表示明显的前景像素,宏义值为1;
GC_PR_BGD-可能为背景像素的像素,宏义义的值为2
GC_PR_FGD-可能为前景像素的像素,宏义义的值为3
rect:算法感兴趣区域。区域之外被标记为明显的背景,这个参数只有当mode=GC_INIT_WITH_RECT才有效。
bgdModel:迭代时使用的背景临时阵列
fgdModel:迭代时使用的前景临时阵列
rect:被用户指定含前景的矩形区域,如果mode设为GC_INIT_WITH_RECT,那么在使用rect对mask进行初始化时,rect区域之外的值统一为0
iterCount:算法迭代次数,迭代次数越多,显然越耗时间,但是对前景和背景的分割也越准。
mode:算法模式。取值如下:
GC_INIT_WITH_RECT:函数使用用户提供的矩形区域进行相关状态和mask的初始化。
GC_INIT_WITH_MASK:函数使用用户提供的mask进行相关状态的初始化。
GC_INIT_WITH_RECT 和 GC_INIT_WITH_MASK可以同时使用,这种情况下,矩形区域外的象素点将被初始化为GC_BGD状态。
GC_EVAL:The value means that the algorithm should just resume.【作者注:读不懂这句话,有读懂的可以加QQ2034196302说出自己的高见】
使用grabCut函数的示例代码如下:
图像处理开发资料、图像处理开发需求、图像处理接私活挣零花钱,可以搜索公众号"qxsf321",并关注!
代码中用到的图像下载链接:https://pan.baidu.com/s/1kUNVMyN 密码:gq5x
//opencv版本:OpenCV3.0
//VS版本:VS2013
//Author:qxsf321.net
#include <opencv2/core/core.hpp>
#include <opencv2/imgproc/imgproc.hpp>
#include <opencv2/imgproc/types_c.h>
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/highgui/highgui_c.h>
#include <iostream>
using namespace cv;
using namespace std;
int main()
{
Mat image = imread("28.jpg");
Mat image_rect;
image_rect = image.clone();
Rect roi_rect(58, 5, 539, 490);//大致圈定图像上的前景对象,(58,3)是ROI区域的左上顶点坐标,539是roi的宽度,490是roi的高度
Mat result;
Mat bgModel, fgModel;
Scalar color = Scalar(0, 0, 255);
rectangle(image_rect, roi_rect, color, 2, 8, 0);//用红色矩形标志出自己设定的大致前景区域
imshow("image_rect", image_rect);
//grabCut()最后一个参数为GC_INIT_WITH_RECT时
grabCut(image, result, roi_rect, bgModel, fgModel, 5,
GC_INIT_WITH_RECT);
compare(result, GC_PR_FGD, result, CMP_EQ);
//result = result & 1 ;
Mat foreground(image.size(), CV_8UC3,
Scalar(128, 128, 128));
image.copyTo(foreground, result);
imshow("Foreground", foreground);
waitKey(0);
return 0;
}
运行结果如下图所示:

本文介绍了Grabcut算法,它是Graphcut的改进版,用于图像的前景与背景分割。Grabcut基于RGB混合高斯模型,通过最小割优化问题实现分割。OpenCV提供grabCut函数来应用此算法,文中给出了函数参数解释和示例代码。
1450





