opencv图像分割 --- Grabcut图像分割
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图像分割相关推荐
- 【OpenCV 4开发详解】分割图像——Grabcut图像分割
本文首发于"小白学视觉"微信公众号,欢迎关注公众号 本文作者为小白,版权归人民邮电出版社发行所有,禁止转载,侵权必究! 经过几个月的努力,小白终于完成了市面上第一本OpenCV 4 ...
- OpenCV图像分割Grabcut算法
前言 1.OpenCV图像分割Grabcut算法主要功能是分割和抠图,就是把框着的目标抠出来,比如要分割出一个证件照的人的图像,只需要在目标外面画一个框,把目标框住,它就可以完成良好的分割. 2.算法 ...
- 图像分割之(四)OpenCV的GrabCut函数使用和源码解读
图像分割之(四)OpenCV的GrabCut函数使用和源码解读 zouxy09@qq.com http://blog.csdn.net/zouxy09 上一文对GrabCut做了一个了解.OpenCV ...
- java grabcut_求教,在用OpenCV java接口调用GrabCut图像分割函数时出现错误
该楼层疑似违规已被系统折叠 隐藏此楼查看此楼 求教,在用OpenCV java接口调用GrabCut图像分割函数时出现错误 代码为: import org.opencv.core.*; import ...
- OpenCV4学习笔记(57)——基于GrabCut图像分割算法实现背景替换与背景虚化效果
在上一篇笔记<OpenCV4学习笔记(56)>中,整理了关于在OpenCV中使用GrabCut图像分割算法的相关内容,那么本次笔记就以GrabCut算法为基础来实现对图像的背景替换和背景虚 ...
- 图像分割GrabCut
OpenCV(EmguCV)2.1新特性介绍之图像分割GrabCut(GrabCut Of OpenCV 2.1) 作者:王先荣 前不久OpenCV和EmguCV相继发布了2.1版,增加了一些 ...
- 图像分割—GrabCut算法
文章目录 一.理论概述 二.OpenCV中grabCut算法函数: 一.理论概述 Grabcut是基于图割(graph cut)实现的图像分割算法,它需要用户输入一个bounding box作为分割目 ...
- OpenCV移植各向异性图像分割间隙流体的实例(附完整代码)
OpenCV移植各向异性图像分割间隙流体的实例 OpenCV移植各向异性图像分割间隙流体的实例 OpenCV移植各向异性图像分割间隙流体的实例 #include "opencv2/openc ...
- 利用OpenCV的Grabcut()函数实现图像的前景与背景的分割-并对Grabcut()作详细介绍
图像处理开发需求.图像处理接私活挣零花钱,请加微信/QQ 2487872782 图像处理开发资料.图像处理技术交流请加QQ群,群号 271891601 Graphcut是一种基于图论的分割方法,在计算 ...
最新文章
- 【智能家居篇】wifi网络结构(上)
- 【android-cocos2d-X2.2 环境配置】在Mac下搭建Cocos2d-X-android开发环境!
- 泛型中的模糊继承,解析T的意义
- msbuild构建步骤_如何按照以下步骤构建最终的AI聊天机器人
- 【初赛】NOIP2018程序模板
- Python之路,Day21 - 常用算法学习
- 软件项目进度控制表(自制)
- 量子计算基础——量子测量
- oracle 12c 容器数据库公共用户去访问pdb数据库
- STM32L452CCU6 STM32L432KCU6 GD32F407VKT6 嵌入式技术数据手册 32位ARM
- Unity 复制内容到剪贴板
- 读 Paxos 到 ZooKeeper ¥ 50大洋
- 飞秋远程可利用0day 的详细分析和利用方法 飞秋漏洞
- 医院预约挂号系统-系统结构
- 简单的Filter过滤器实现
- 【架构师】零基础到精通——架构发展
- Git中rebase的使用
- 数字图像处理|Matlab-基于颜色的车牌识别程序
- SQL Server中对比表数量,索引数量及procedure数量
- SolidWorks直播课 | 3D参数化建模的实现方式