算法的原理参见papaer:“GrabCut” — Interactive Foreground Extraction using Iterated Graph Cuts
grabcut函数原理
即选定一个四边形框,把框中的图像作为grabcut的一个输入参数,表示该框中的像素可能属于前景,但框外的部分一定属于背景。
在opencv 中grabcut 原函数的定义:
//! segments the image using GrabCut algorithm
CV_EXPORTS_W void grabCut
(
InputArray img,
InputOutputArray mask,
Rect rect,(包含前景的矩形)
InputOutputArray bgdModel, (前景)
InputOutputArray fgdModel,(背景)
int iterCount, (迭代次数)
int mode = GC_EVAL );
rectangle原函数:
CV_EXPORTS void rectangle
(CV_IN_OUT Mat& img, Rect rec,
const Scalar& color, int thickness=1,
int lineType=8, int shift=0);
本例程对整幅图像进行物体检测,即用grabcut检测前景物体。
程序运行的速度与iteration(即迭代的次数)有关。iteration越大,运行时间越长。
#include
#include
#include "opencv2/imgproc/imgproc.hpp"
#include
#include
using namespace std;
using namespace cv;
int main(int argc, char* argv[])
{
//计算时间
clock_t start, end;
start = clock();
Mat image = imread("1.jpg");
Mat result; // 分割结果 (4种可能取值)
Mat bgModel, fgModel; // 模型(内部使用)
// 设定矩形,该矩形的长宽分别-1
Rect rectangle(1, 1, image.cols - 1, image.rows - 1);
grabCut(image, result, rectangle, bgModel, fgModel, 1, cv::GC_INIT_WITH_RECT);
// 得到可能为前景的像素
compare(result, cv::GC_PR_FGD, result, cv::CMP_EQ);
// 生成输出图像
Mat foreground(image.size(), CV_8UC3, cv::Scalar(255, 255, 255));
image.copyTo(foreground, result); // 不复制背景数据
// 包含矩形的原始图像
cv::rectangle(image, rectangle, cv::Scalar(0, 0, 0), 1);
cv::namedWindow("Orginal Image");
cv::imshow("Orginal Image", image);
// 输出前景图像结果
cv::namedWindow("Foreground Of Segmented Image");
cv::imshow("Foreground Of Segmented Image", foreground);
end = clock();
cout << "Run time: " << (double)(end - start) / CLOCKS_PER_SEC << "S" << endl;
cvWaitKey(0); //等待退出
//cvReleaseImage(&image);
return 0;
}
效果如图:
原图像
运行之后的结果(白色部分为背景)