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;//两个临时矩阵变量,作为算法的中间变量使用,不用carecv::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

时间: 2024-09-11 05:21:38

OpenCV学习(20) grabcut分割算法的相关文章

OpenCV学习(21) Grabcut算法详解

grab cut算法是graph cut算法的改进.在理解grab cut算之前,应该学习一下graph cut算法的概念及实现方式. 我搜集了一些graph cut资料:http://yunpan.cn/QGDVdBXwkXutH      grab cut算法详细描述见资料中的pdf文件:"GrabCut" - Interactive Foreground Extraction using Iterated Graph Cuts      grab cut算法是一种基于图论的图像分

OpenCV学习(8) 分水岭算法(2)

    现在我们看看OpenCV中如何使用分水岭算法.     首先我们打开一副图像:    // 打开另一幅图像   cv::Mat    image= cv::imread("../tower.jpg");     if (!image.data)         {         cout<<"不能打开图像!"<<endl;         return 0;         }      接下来,我们要创建mark图像.mark图像

(转) OpenCV学习笔记大集锦 与 图像视觉博客资源2之MIT斯坦福CMU

      首页 视界智尚 算法技术 每日技术 来打我呀 注册     OpenCV学习笔记大集锦 整理了我所了解的有关OpenCV的学习笔记.原理分析.使用例程等相关的博文.排序不分先后,随机整理的.如果有好的资源,也欢迎介绍和分享. 1:OpenCV学习笔记 作者:CSDN数量:55篇博文网址:http://blog.csdn.net/column/details/opencv-manual.html 2:部分OpenCV的函数解读和原理解读 作者:梦想腾飞数量:20篇博文网址:http:/

用Spark学习矩阵分解推荐算法

在矩阵分解在协同过滤推荐算法中的应用中,我们对矩阵分解在推荐算法中的应用原理做了总结,这里我们就从实践的角度来用Spark学习矩阵分解推荐算法. 1. Spark推荐算法概述 在Spark MLlib中,推荐算法这块只实现了基于矩阵分解的协同过滤推荐算法.而基于的算法是FunkSVD算法,即将m个用户和n个物品对应的评分矩阵M分解为两个低维的矩阵: 其中k为分解成低维的维数,一般远比m和n小.如果大家对FunkSVD算法不熟悉,可以复习对应的原理篇. 2. Spark推荐算法类库介绍 在Spar

指针-opencv学习灰度图锐化的两个函数的差别不理解

问题描述 opencv学习灰度图锐化的两个函数的差别不理解 下面是一个灰度图锐化的函数,我有两种方式实现,方式1,和方式2,居然得到的结果不一样,图片数据也不一样,请高手看一下,可能是C语言的知识掌握的不好. void my_sharpen(const cv::Mat &image, cv::Mat &result) { result.create (image.size(), image.type ()); for(int j=1; j<image.rows-1; j++) { u

OpenCV提取视频关键帧的算法

问题描述 OpenCV提取视频关键帧的算法 如题,好像OpenCV里没有封装好的函数,有没有做过的朋友知道的?或者提取关键帧 的算法? 解决方案 提取关键帧要看你设定的提取条件吧,最蠢的办法是弄个帧缓存池和一个帧指针(也就是一个计数器),然后用提取每一帧的时候进行条件判断,满足的就存入缓存池中,用帧指定提取指定的帧 解决方案二: 视频关键帧提取最新版ffmpeg 提取视频关键帧最新版ffmpeg 提取视频关键帧 解决方案三: 你可以参考<opencv 计算机视觉编程攻略>

android 代码实现学习中艾宾浩斯遗忘曲线算法

问题描述 android 代码实现学习中艾宾浩斯遗忘曲线算法 有没有关于Android开发学习软件中,实现关于记性.复习使用艾宾浩斯遗忘曲线的?求解? 解决方案 参考:http://baike.baidu.com/link?url=8ugxF94oSkAptHnqVRhIjNRQwQKYkWAcCLysn1Cs0lXRpihSgdMEgQ8YwtK1wEnmyGMTVYfcNlIjbkmF6OnPTTffPyPuJUGdtfcuxtGZPjcALtDuWuyiQkhnJFNr0PeSt74mnO

《深度学习导论及案例分析》一1.3深度学习的模型和算法

1.3深度学习的模型和算法 深度学习亦称深度机器学习.深度结构学习.分层学习,是一类有效训练深层神经网络(Deep Neural Network,DNN)的机器学习算法,可以用于对数据进行高层抽象建模.广义上说,深层神经网络是一种具有多个处理层的复杂结构,其中包含多重非线性变换.如果深度足够,那么多层感知器无疑是深层网络,前馈神经网络也是深层网络.基本的深层网络模型可以分为两大类:生成模型和判别模型.生成是指从隐含层到输入数据的重构过程,而判别是指从输入数据到隐含层的归约过程.复杂的深层结构可能

OpenCV学习(29) 凸包(convexhull)

      在opencv中,通过函数convexHulll能很容易的得到一系列点的凸包,比如由点组成的轮廓,通过convexHull函数,我们就能得到轮廓的凸包.下面的图就是一些点集的凸包.   求凸包的代码如下: int main( int /*argc*/, char** /*argv*/ )     {     Mat img(500, 500, CV_8UC3);     RNG& rng = theRNG();     cout << "\n这个程序演示了凸包函数