Grabcut图像分割与GMM、KMeans、分水岭分割的区别在于, Grabcut图像分割是用户可以

选择目标图像,然后将剩余的作为背景,目标作为前景进行分割,这样可以把目标提取出来,也就

是抠图;而其他三个分割算法是不需要人为干预的,通过算法将图像分割为几个部分。

Grabcut 算法主要运用于计算机视觉中的前背景分割立体视觉抠图等。该算法利用了图像

中的纹理(颜色)信息和边界(反差)信息,只要少量的用户交互操作即可得到比较好的分割结

果.

1. Grabcut 的目标和背景的模型是RGB三通道的混合高斯模型GMM;

2. Grab Cut为一个不断进行分割估计和模型参数学习的交互迭代过程

3. Grab Cut只需要提供背景区域的像素集就可以了。也就是说你只需要框选目标,那么在方框外的像素全部当成背景,这时候就可以对GMM进行建模和完成良好的分割了。即Grab Cut允许不完全的标注.

opencv中Grabcut的相关API:

void grabCut( InputArray img,           //输入图像,必须是8位3通道图像,在处理过程中不会被修改InputOutputArray mask,    //掩码图像,用来确定哪些区域是背景,前景,可能是背景, 可能是前景等//mask既可以作为输入也可以作为输出。作为输入时,mode要                                                    选择GC_INIT_WITH_MASK (=1);GCD_BGD (=0), 背景;    GCD_FGD (=1),前景;  GCD_PR_BGD (=2),可能是背景;    GCD_PR_FGD(=3),可能是前景如果没有手工标记GCD_BGD 或者GCD_FGD,那么结果只会有 GCD_PR_BGD 和 GCD_PR_FGD Rect rect,                //包含前景的矩形,格式为(x, y, w, h)InputOutputArray bgdModel,//算法内部使用的数组,只需要创建大小为(1,65), 数据类型为np.float64的数组InputOutputArray fgdModel,//同上int iterCount,            //算法迭代的次数int mode = GC_EVAL        //用来指示grabCut函数进行什么操作// GC_INIT_WITH_RECT (=0),用矩形窗初始化GrabCut;// GC_INIT_WITH_MASK (=1),用掩码图像初始化GrabCut);

有关鼠标操作的两个函数: 

 void setMousecallback(const string& winname, MouseCallback onMouse, void* userdata=0)winname:窗口的名字onMouse:鼠标响应函数,回调函数。指定窗口里每次鼠标时间发生的时候,被调用的函数指针。 这个函数的原型应该为void on_Mouse(int event, int x, int y, int flags, void* param);userdate:传给回调函数的参数 
void OnMouseAction( int event,  // 代表了鼠标的各种操作int x,      // 代表鼠标位于窗口的(x,y)坐标位置,即Point(x,y)int y,      int flags,  // 代表鼠标的拖拽事件,以及键盘鼠标联合事件void *ustc  // 标识了所响应的事件函数);
int event:#define CV_EVENT_MOUSEMOVE 0             //滑动
#define CV_EVENT_LBUTTONDOWN 1           //左键点击
#define CV_EVENT_RBUTTONDOWN 2           //右键点击
#define CV_EVENT_MBUTTONDOWN 3           //中键点击
#define CV_EVENT_LBUTTONUP 4             //左键放开
#define CV_EVENT_RBUTTONUP 5             //右键放开
#define CV_EVENT_MBUTTONUP 6             //中键放开
#define CV_EVENT_LBUTTONDBLCLK 7         //左键双击
#define CV_EVENT_RBUTTONDBLCLK 8         //右键双击
#define CV_EVENT_MBUTTONDBLCLK 9         //中键双击
int flags:#define CV_EVENT_FLAG_LBUTTON 1       //左鍵拖曳
#define CV_EVENT_FLAG_RBUTTON 2       //右鍵拖曳
#define CV_EVENT_FLAG_MBUTTON 4       //中鍵拖曳
#define CV_EVENT_FLAG_CTRLKEY 8       //(8~15)按Ctrl不放事件
#define CV_EVENT_FLAG_SHIFTKEY 16     //(16~31)按Shift不放事件
#define CV_EVENT_FLAG_ALTKEY 32       //(32~39)按Alt不放事件

Grabcut 算法的代码展示:

/*图像中对象抠图
*/#include<iostream>
#include<opencv2/opencv.hpp>
#include<math.h>using namespace std;
using namespace cv;Mat src, image;
Mat mask, bgModel, fgModel;const char* winTitle = "input image";
Rect rect;
int num; //迭代的次数
bool init = false;void onMouse(int event, int x, int y, int flags, void* param);void showImage();void setROIMask();void runGrabCut();int main(int argc, char** argv)
{src = imread("E:/技能学习/opencv图像分割/flower.jpg");if (src.empty()){cout << "could not load image!" << endl;return -1;}mask.create(src.size(), CV_8UC1);mask.setTo(Scalar::all(GC_BGD)); //将mask设置为背景namedWindow(winTitle, WINDOW_AUTOSIZE);setMouseCallback(winTitle, onMouse, 0);  //鼠标回调函数imshow(winTitle, src);while (true){char c = (char)waitKey(0);if (c == ' ') //选中矩形框后,按空格键执行grabcut分割{runGrabCut(); //开始图割算法,运行一次为迭代一次num++; //迭代次数加1showImage(); //显示图像//imshow("背景", bgModel);//imshow("前景", fgModel);cout << "current iteative time:" << num << endl;}if ((int)c == 27) //检测是否按下esc键{break;}}waitKey(0);destroyAllWindows();return 0;
}void onMouse(int event, int x, int y, int flags, void* param)
{switch (event){case EVENT_LBUTTONDOWN: //鼠标按下rect.x = x;rect.y = y;rect.width = 1;rect.height = 1;init = false;num = 0;break;case EVENT_MOUSEMOVE:  //鼠标移动if (flags & EVENT_FLAG_LBUTTON) //鼠标左键拖拽{rect = Rect(Point(rect.x, rect.y), Point(x, y));showImage();}break;case EVENT_LBUTTONUP: //鼠标左边弹起if (rect.width > 1 && rect.height > 1){showImage();}break;}
}void showImage()
{Mat result,binMask;binMask.create(mask.size(), CV_8UC1);binMask = mask & 1; //进一步掩膜if (init)  //进一步抠出无效区域。鼠标按下,init变为false{src.copyTo(result, binMask);}else{src.copyTo(result);}rectangle(result, rect, Scalar(0, 0, 255), 2, 8);imshow(winTitle, result);
}void setROIMask()
{/*GC_BGD = 0:表示明确属于背景的像素GC_FGD = 1:表示明确属于前景的像素GC_PR_BGD = 2:表示可能属于背景的像素GC_PR_FGD = 3:表示可能属于前景的像素*/mask.setTo(GC_BGD); //全部设置为背景//防止出界rect.x = max(0, rect.x);rect.y = max(0, rect.y);rect.width = min(rect.width, src.cols - rect.x);rect.height = min(rect.height, src.rows - rect.y);//从mask中截取选中的矩形,将其作为可能的前景mask(rect).setTo(Scalar(GC_PR_FGD));
}void runGrabCut()
{if (rect.width < 2 && rect.height < 2){return;}if (init) //鼠标按下,init变为false{grabCut(src, mask, rect, bgModel, fgModel, 1); //第二次迭代,用mask初始化grabcut}else{grabCut(src, mask, rect, bgModel, fgModel, 1, GC_INIT_WITH_RECT);//用矩形框初始化grabcutinit = true;}}

结果展示:

opencv图像分割 --- Grabcut图像分割相关推荐

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

    本文首发于"小白学视觉"微信公众号,欢迎关注公众号 本文作者为小白,版权归人民邮电出版社发行所有,禁止转载,侵权必究! 经过几个月的努力,小白终于完成了市面上第一本OpenCV 4 ...

  2. OpenCV图像分割Grabcut算法

    前言 1.OpenCV图像分割Grabcut算法主要功能是分割和抠图,就是把框着的目标抠出来,比如要分割出一个证件照的人的图像,只需要在目标外面画一个框,把目标框住,它就可以完成良好的分割. 2.算法 ...

  3. 图像分割之(四)OpenCV的GrabCut函数使用和源码解读

    图像分割之(四)OpenCV的GrabCut函数使用和源码解读 zouxy09@qq.com http://blog.csdn.net/zouxy09 上一文对GrabCut做了一个了解.OpenCV ...

  4. java grabcut_求教,在用OpenCV java接口调用GrabCut图像分割函数时出现错误

    该楼层疑似违规已被系统折叠 隐藏此楼查看此楼 求教,在用OpenCV java接口调用GrabCut图像分割函数时出现错误 代码为: import org.opencv.core.*; import ...

  5. OpenCV4学习笔记(57)——基于GrabCut图像分割算法实现背景替换与背景虚化效果

    在上一篇笔记<OpenCV4学习笔记(56)>中,整理了关于在OpenCV中使用GrabCut图像分割算法的相关内容,那么本次笔记就以GrabCut算法为基础来实现对图像的背景替换和背景虚 ...

  6. 图像分割GrabCut

    OpenCV(EmguCV)2.1新特性介绍之图像分割GrabCut(GrabCut Of OpenCV 2.1) 作者:王先荣     前不久OpenCV和EmguCV相继发布了2.1版,增加了一些 ...

  7. 图像分割—GrabCut算法

    文章目录 一.理论概述 二.OpenCV中grabCut算法函数: 一.理论概述 Grabcut是基于图割(graph cut)实现的图像分割算法,它需要用户输入一个bounding box作为分割目 ...

  8. OpenCV移植各向异性图像分割间隙流体的实例(附完整代码)

    OpenCV移植各向异性图像分割间隙流体的实例 OpenCV移植各向异性图像分割间隙流体的实例 OpenCV移植各向异性图像分割间隙流体的实例 #include "opencv2/openc ...

  9. 利用OpenCV的Grabcut()函数实现图像的前景与背景的分割-并对Grabcut()作详细介绍

    图像处理开发需求.图像处理接私活挣零花钱,请加微信/QQ 2487872782 图像处理开发资料.图像处理技术交流请加QQ群,群号 271891601 Graphcut是一种基于图论的分割方法,在计算 ...

最新文章

  1. 【智能家居篇】wifi网络结构(上)
  2. 【android-cocos2d-X2.2 环境配置】在Mac下搭建Cocos2d-X-android开发环境!
  3. 泛型中的模糊继承,解析T的意义
  4. msbuild构建步骤_如何按照以下步骤构建最终的AI聊天机器人
  5. 【初赛】NOIP2018程序模板
  6. Python之路,Day21 - 常用算法学习
  7. 软件项目进度控制表(自制)
  8. 量子计算基础——量子测量
  9. oracle 12c 容器数据库公共用户去访问pdb数据库
  10. STM32L452CCU6 STM32L432KCU6 GD32F407VKT6 嵌入式技术数据手册 32位ARM
  11. Unity 复制内容到剪贴板
  12. 读 Paxos 到 ZooKeeper ¥ 50大洋
  13. 飞秋远程可利用0day 的详细分析和利用方法 飞秋漏洞
  14. 医院预约挂号系统-系统结构
  15. 简单的Filter过滤器实现
  16. 【架构师】零基础到精通——架构发展
  17. Git中rebase的使用
  18. 数字图像处理|Matlab-基于颜色的车牌识别程序
  19. SQL Server中对比表数量,索引数量及procedure数量
  20. SolidWorks直播课 | 3D参数化建模的实现方式

热门文章

  1. idea下springboot导出war包
  2. 一分钟掌握js中的map方法
  3. Python爬虫教程:urllib 基础使用(三)
  4. 记录ubuntu建立新用户并赋予root权限
  5. Geomagic Touch(LAN口版本) 环境配置及驱动安装【过程记录】
  6. JSONField 注解的使用
  7. jq添加数组_jquery 数组 添加元素
  8. 系统准备工具3.14永久关闭
  9. redis使用scan模糊匹配key
  10. Animation Frame动画实现应用的欢迎界面