OpenCV学习(20) grabcut分割算法
http://www.cnblogs.com/mikewolf2002/p/3330390.html
OpenCV学习(20) grabcut分割算法
在OpenCV中,实现了grabcut分割算法,该算法可以方便的分割出前景图像,操作简单,而且分割的效果很好。算法的原理参见papaer:“GrabCut” — Interactive Foreground Extraction using Iterated Graph Cuts
比如下面的一副图,我们只要选定一个四边形框,把框中的图像作为grabcut的一个输入参数,表示该框中的像素可能属于前景,但框外的部分一定属于背景。
然后调用grabcut函数,就可以分割出城堡来。具体代码如下:
// 打开另一幅图像
cv::Mat image= cv::imread("../tower.jpg");
if (!image.data)
{
cout<<"不能打开图像!"<<endl;
return 0;
} // 矩形外的像素是背景
cv::Rect rectangle(50,70,image.cols-150,image.rows-180); cv::Mat result;
//两个临时矩阵变量,作为算法的中间变量使用,不用care
cv::Mat bgModel,fgModel;
double tt = cv::getTickCount();
// GrabCut 分段
cv::grabCut(image, //输入图像
result, //分段结果
rectangle,// 包含前景的矩形
bgModel,fgModel, // 前景、背景
1, // 迭代次数
cv::GC_INIT_WITH_RECT); // 用矩形
tt = cv::getTickCount() - tt;
printf("算法执行执行时间:%g ms\n", tt/cv::getTickFrequency()*1000);
// 得到可能是前景的像素
//比较函数保留值为GC_PR_FGD的像素
cv::compare(result,cv::GC_PR_FGD,result,cv::CMP_EQ);
// 产生输出图像
cv::Mat foreground(image.size(),CV_8UC3,cv::Scalar(255,255,255));
//背景值为 GC_BGD=0,作为掩码
image.copyTo(foreground,result);
grabCut函数的第一个参数为我们要处理的图像,本程序中就是image,图像的类型必须为:CV_8UC3
第二个参数是mask图像,它的大小和image一样,但是它的格式为CV_8UC1,只能是单通道的,grabcut算法的结果就保存在该图像中。
前面的代码中,我们并没有对mask图像(result)进行初始化设置,因为第6个参数为cv::GC_INIT_WITH_RECT,它表示算法会根据rectangle的范围,来生成一个初始化的mask图像。
cv::grabCut(image, //输入图像
result, //分段结果
rectangle, // 包含前景的矩形
bgModel,fgModel, // 前景、背景
1, // 迭代次数
cv::GC_INIT_WITH_RECT); // 用矩形
mask图像的值只能为下面下面4个值(PR,probably表示可能的):
GC_BGD = 0, //背景
GC_FGD = 1, //前景
GC_PR_BGD = 2, //可能背景
GC_PR_FGD = 3 //可能前景
根据rectangle生成的mask图像规则为:四边形外面的部分一定是背景,所以在mask图中对应的像素值为GC_BGD,而四边形内部的的值可能为前景,所以对应的像素值为GC_PR_FGD。所以我们程序中使用mask图像应该如下图所示。
如果第7个参数为GC_INIT_WITH_MASK,这时第三个参数rectangle没有使用,我们必须在调用grabcut函数之前,手工设置mask图像(变量result),如果我们把result设置成上图所示的灰度图。那个调用函数
cv::grabCut(image1, //输入图像
result1, //分段结果
rectangle, // 包含前景的矩形
bgModel,fgModel, // 前景、背景
1, // 迭代次数
cv::GC_INIT_WITH_MASK); // 用矩形
可以得到同样的结果。
可以参考下面的代码:
cv::Mat result1= cv::Mat(image1.rows, image1.cols,CV_8UC1, cv::Scalar(cv::GC_BGD));
//注意给子矩阵赋值的方法
cv::Mat roi(result1, cv::Rect(50,70,result1.cols-150,result.rows-180));
roi = cv::Scalar(cv::GC_PR_FGD);
tt = cv::getTickCount();
// GrabCut 分段
cv::grabCut(image1, //输入图像
result1, //分段结果
rectangle,// 包含前景的矩形
bgModel,fgModel, // 前景、背景
1, // 迭代次数
cv::GC_INIT_WITH_MASK); // 用矩形
tt = cv::getTickCount() - tt;
printf("算法执行执行时间:%g ms\n", tt/cv::getTickFrequency()*1000); // 得到可能是前景的像素
//比较函数保留值为GC_PR_FGD的像素
cv::compare(result1,cv::GC_PR_FGD,result,cv::CMP_EQ);
// 产生输出图像
cv::Mat foreground1(image1.size(),CV_8UC3,cv::Scalar(255,255,255));
//背景值为 GC_BGD=0,作为掩码
image.copyTo(foreground1,result1);
第3个参数是rectangle的大小位置,如果第7个参数为GC_INIT_WITH_MASK,则该参数没有作用。
第4,5个参数是两个算法在执行过程中使用临时矩阵变量,不用care它们的内容。
第6个参数是迭代次数,迭代越多,效果越好,但划时间也越长。
第7个参数是操作模式,通常情况下为GC_INIT_WITH_RECT和GC_INIT_WITH_MASK。
从上面的图中,我们可以看到,grabcut算法的效果很好,但是花的时间也很长,上面图像在我的笔记本上需要4.4秒。
程序源代码:工程FirstOpenCV13
OpenCV学习(20) grabcut分割算法的更多相关文章
- OpenCV学习(21) Grabcut算法详解
grab cut算法是graph cut算法的改进.在理解grab cut算之前,应该学习一下graph cut算法的概念及实现方式. 我搜集了一些graph cut资料:http://yunpan. ...
- OpenCV学习(23) 使用kmeans算法实现图像分割
本章我们用kmeans算法实现一个简单图像的分割.如下面的图像,我们知道图像分3个簇,背景.白色的任务,红色的丝带以及帽子. Mat img = cv::imread(&quo ...
- 《opencv学习》 之 OTSU算法实现二值化
主要讲解OTSU算法实现图像二值化: 1.统计灰度级图像中每个像素值的个数. 2.计算第一步个数占整个图像的比例. 3.计算每个阈值[0-255]条件下,背景和前景所包含像素值总个数和总概率(就 ...
- OpenCV 学习笔记 04 深度估计与分割——GrabCut算法与分水岭算法
1 使用普通摄像头进行深度估计 1.1 深度估计原理 这里会用到几何学中的极几何(Epipolar Geometry),它属于立体视觉(stereo vision)几何学,立体视觉是计算机视觉的一个分 ...
- Opencv学习之路—Opencv下基于HOG特征的KNN算法分类训练
在计算机视觉研究当中,HOG算法和LBP算法算是基础算法,但是却十分重要.后期很多图像特征提取的算法都是基于HOG和LBP,所以了解和掌握HOG,是学习计算机视觉的前提和基础. HOG算法的原理很多资 ...
- 基于标记的分水岭分割算法/OpenCV中距离变换
Opencv分水岭算法——watershed自动图像分割用法 OpenCV距离变换distanceTransform应用 图像分割作为图像识别的基础,在图像处理中占有重要地位,通常需要在进行图像分割算 ...
- OpenCV学习笔记(27)KAZE 算法原理与源码分析(一)非线性扩散滤波
http://blog.csdn.net/chenyusiyuan/article/details/8710462 OpenCV学习笔记(27)KAZE 算法原理与源码分析(一)非线性扩散滤波 201 ...
- OpenCV 学习笔记03 凸包convexHull、道格拉斯-普克算法Douglas-Peucker algorithm、approxPloyDP 函数
凸形状内部的任意两点的连线都应该在形状里面. 1 道格拉斯-普克算法 Douglas-Peucker algorithm 这个算法在其他文章中讲述的非常详细,此处就详细撰述. 下图是引用维基百科的.ε ...
- OpenCV学习(8) 分水岭算法(2)
现在我们看看OpenCV中如何使用分水岭算法. 首先我们打开一副图像: // 打开另一幅图像 cv::Mat image= cv::imread("../to ...
随机推荐
- 使用Chrome DevTools的Timeline和Profiles提高Web应用程序的性能
来源: http://www.oschina.net/translate/performance-optimisation-with-timeline-profiles 我们都希望创建高性能的Web应 ...
- C#中的Virtual、Override和new关键词理解
来源:http://blog.csdn.net/jackiezhw/article/details/2673992 在 C# 中,派生类可以包含与基类方法同名的方法. 基类方法必须定义为 virtua ...
- 转载,find.sh
#!/bin/bash #find files contains a keyword #write by xiaojing.zhao #2012.12.14 echo -e "\nThis ...
- web-service客户端与服务器端的连接
1 首先讲解下xfire XFire是新一代的Java Web服务引擎,XFire使得在JavaEE应用中发布Web服务变得轻而易举.和其他Web服务引擎相比,XFire的配置非常简单,可以非常容易地 ...
- springmvc 关于controller的字符编码
在使用springMVC框架构建web应用,客户端常会请求字符串.整型.json等格式的数据,通常使用@ResponseBody注解使 controller回应相应的数据而不是去渲染某个页面.如果请求 ...
- WPF中静态引用资源与动态引用资源的区别
WPF中静态引用资源与动态引用资源的区别 WPF中引用资源分为静态引用与动态引用,两者的区别在哪里呢?我们通过一个小的例子来理解. 点击“Update”按钮,第2个按钮的文字会变成“更上一层楼”, ...
- Android中购物车的全选、反选、问题和计算价格
此Demo主要解决的是购物车中的全选,反选计算价格和选中的条目个数的问题,当选中几条时,点击反选,会把当先选中的变为不选中,把不选中的变为选中.点击全选会全部选中,再次点击时,变为全部不选中. //- ...
- SonarQube代码质量管理平台比较好的搭建和使用资料
http://www.voidcn.com/blog/lidujun1028/article/p-3831235.html Sonar (SonarQube)是一个开源平台,用于管理源代码的质量. ...
- 转:HTTP协议详解(真的很经典)
转自:http://blog.csdn.net/gueter/archive/2007/03/08/1524447.aspx Author :Jeffrey 引言 HTTP是一个属于应用层的面向对象的 ...
- 【spring boot】SpringBoot初学(2) - properties配置和读取
前言 只是简单的properties配置学习,修改部分"约定"改为自定义"配置".真正使用和遇到问题是在细看. 一.主要 核心只是demo中的: @Proper ...