【OpenCV 4开发详解】分割图像——Grabcut图像分割

本文首发于 “小白学视觉”微信公众号,欢迎关注公众号
本文作者为小白,版权归 人民邮电出版社发行所有,禁止转载,侵权必究!

经过几个月的努力,小白终于完成了市面上第一本OpenCV 4入门书籍《OpenCV 4开发详解》。为了更让小伙伴更早的了解最新版的OpenCV 4,小白与出版社沟通,提前在公众号上连载部分内容,请持续关注小白。

Grabcut算法是重要的图像分割算法,其使用高斯混合模型估计目标区域的背景和前景。该算法通过迭代的方法解决了能量函数最小化的问题,使得结果具有更高的可靠性。OpenCV 4提供了利用Grabcut算法分割图像的grabCut()函数,该函数的函数原型在代码清单8-21中给出。

代码清单8-21 grabCut()函数原型
1.	void cv::grabCut(InputArray  img,
2.	                     InputOutputArray  mask,
3.	                     Rect  rect,
4.	                     InputOutputArray  bgdModel,
5.	                     InputOutputArray  fgdModel,
6.	                     int  iterCount,
7.	                     int  mode = GC_EVAL 
8.	                     )
  • img:输入的待分割图像,数据类型为CV_8U的三通道图像。
  • mask:用于输入、输出的CV_8U单通道掩码图像,图像中像素值的取值范围以及含义在表8-4给出。
  • rect:包含对象的ROI区域,该参数仅在mode == GC_INIT_WITH_RECT时使用。
  • bgdModel:背景模型的临时数组。
  • fgdModel:前景模型的临时数组。
  • iterCount:算法需要进行的迭代次数。
  • mode:分割模式标志,该参数值可选择范围以及含义在表8-5给出。
表8-4 grabCut()函数中掩码图像像素值范围和含义
标志参数 简记 含义
GC_BGD 0 明显为背景的像素
GC_FGD 1 明显为前景(对象)的像素
GC_PR_BGD 2 可能为背景的像素
GC_PR_FGD 3 可能为前景(对象)的像素
表8-5 grabCut()函数中分割模式标志取值范围和含义
标志参数 简记 含义
GC_INIT_WITH_RECT 0 使用提供的矩形初始化状态和掩码,之后根据算法进行迭代更新
GC_INIT_WITH_MASK 1 使用提供的掩码初始化状态,可以组合GC_INIT_WITH_RECT和GC_INIT_WITH_MASK。然后,使用GC_BGD自动初始化ROI外部的所有像素。
GC_EVAL 2 算法应该恢复
GC_EVAL_FREEZE_MODEL 3 只使用固定模型运行grabCut算法(单次迭代)

该函数实现了GrabCut图像分割算法,函数的第一个参数是待分割的输入图像,要求是CV_8U的三通道彩色图像。第二个参数是掩码矩阵,该参数既用于输入又用于输出,当最后一个参数设置为GC_INIT_WITH_RECT时,该矩阵会被设置为初始掩码,掩码矩阵中具有4个可选择的参数,分别是0(GC_BGD)表示明显为背景的像素、1(GC_FGD)表示明显为前景或者对象的像素、2(GC_PR_BGD)表示疑似背景的像素、3(GC_PR_FGD)表示疑似前景或者对象的像素。最后图像的分割结果也是通过分析掩码矩阵中每个像素的数值进行提取。函数第三个参数是需要进行分割去ROI区域,在ROI区域的外部会被标记为“明显的背景”区域,该参数尽在mode == GC_INIT_WITH_RECT时使用。函数第四个和第五个参数分别是背景模型、前景模型的临时数组,需要注意的是在处理同一图像时,请勿对它进行修改。函数第六个参数是算法进行迭代的次数。函数最后一个参数是分割模式标志,可以选择的参数及其含义在表8-5给出。

为了了解该函数的使用方法以及对图像的分割效果,在代码清单8-22中给出了通过grabCut()函数对图像进行分割的示例程序。程序中首先在原图像中选择ROI矩形区域,之后利用grabCut()函数对该区域分割,计算前景和背景,最后将掩码矩阵中明显是前景和疑似前景的像素点全部输出,程序运行结果如图8-14所示。需要说明的是程序中为了保证绘制矩形框不对图像分割产生影响,在绘制矩形框时对原图像进行了深拷贝。

代码清单8-22 myGrabCut.cpp利用grabCuts方法图像分割
1.	#include <opencv2/opencv.hpp>
2.	#include <iostream>
3.	
4.	using namespace cv;
5.	using namespace std;
6.	
7.	int main()
8.	{
9.		Mat img = imread("lena.png");
10.		if (!img.data)  //防止错误读取图像
11.		{
12.			cout<<"请确认图像文件名称是否正确" << endl; 
13.			return 0;
14.		}
15.	
16.		//绘制矩形
17.		Mat imgRect;
18.		img.copyTo(imgRect);  //备份图像,方式绘制矩形框对结果产生影响
19.		Rect rect(80, 30, 340, 390);
20.		rectangle(imgRect, rect, Scalar(255, 255, 255),2);
21.		imshow("选择的矩形区域", imgRect);
22.	
23.		//进行分割
24.		Mat bgdmod = Mat::zeros(1, 65, CV_64FC1);
25.		Mat fgdmod = Mat::zeros(1, 65, CV_64FC1);
26.		Mat mask = Mat::zeros(img.size(), CV_8UC1);
27.		grabCut(img, mask, rect, bgdmod, fgdmod, 5, GC_INIT_WITH_RECT);
28.		
29.		//将分割出的前景绘制回来
30.		Mat result;
31.		for (int row = 0; row < mask.rows; row++) 
32.		{
33.			for (int col = 0; col < mask.cols; col++) 
34.			{
35.				int n = mask.at<uchar>(row, col);
36.				//将明显是前景和可能是前景的区域都保留
37.				if (n == 1 || n == 3) 
38.				{
39.					mask.at<uchar>(row, col) = 255;
40.				}
41.				//将明显是背景和可能是背景的区域都删除
42.				else 
43.				{
44.					mask.at<uchar>(row, col) = 0;
45.				}
46.			}
47.		}
48.		bitwise_and(img, img, result, mask);
49.		imshow("分割结果", result);
50.		waitKey(0);
51.		return 0;
52.	}
【OpenCV 4开发详解】分割图像——Grabcut图像分割_第1张图片
图8-14 myGrabCut.cpp程序中选择的区域和分割结果

 

OpenCV 4开发详解
往期推荐
【OpenCV 4开发详解】图像卷积
【OpenCV 4开发详解】图像噪声的种类与生成
【OpenCV 4开发详解】均值滤波
【OpenCV 4开发详解】方框滤波
【OpenCV 4开发详解】高斯滤波
【OpenCV 4开发详解】可分离滤波
【OpenCV 4开发详解】中值滤波
【OpenCV 4开发详解】边缘检测原理
【OpenCV 4开发详解】Scharr算子
【OpenCV 4开发详解】Laplacian算子
【OpenCV 4开发详解】Canny算法
【OpenCV 4开发详解】图像距离变换
【OpenCV 4开发详解】图像连通域分析
【OpenCV 4开发详解】图像腐蚀
【OpenCV 4开发详解】图像膨胀
【OpenCV 4开发详解】形态学应用
【OpenCV 4开发详解】检测直线
【OpenCV 4开发详解】直线拟合
【OpenCV 4开发详解】直线检测
【OpenCV 4开发详解】轮廓发现与绘制
【OpenCV 4开发详解】轮廓面积与长度
【OpenCV 4开发详解】图像矩的计算与应用
【OpenCV 4开发详解】点集拟合
【OpenCV 4开发详解】QR二维码检测
【OpenCV 4开发详解】分割图像——漫水填充法
【OpenCV 4开发详解】分割图像——分水岭法
经过几个月的努力,市面上第一本OpenCV 4入门书籍《OpenCV 4开发详解》将春节后由人民邮电出版社发行。如果小伙伴觉得内容有帮助,希望到时候多多支持!
关注小白的小伙伴可以提前看到书中的内容,我们创建了学习交流群,欢迎各位小伙伴添加小白微信加入交流群,添加小白时请备注“学习OpenCV 4”。
【OpenCV 4开发详解】分割图像——Grabcut图像分割_第2张图片
【OpenCV 4开发详解】分割图像——Grabcut图像分割_第3张图片

你可能感兴趣的:(OpenCV,4开发详解)