OpenCV中Grabcut算法的具体使用

目录
  • Grabcut 算法的基本步骤:
  • Grabcut的相关API:
  • Grabcut 算法的代码示例:

Grabcut 算法主要运用于计算机视觉中的前背景分割,立体视觉和抠图等。该算法利用了图像中的纹理(颜色)信息和边界(反差)信息,只要少量的用户交互操作即可得到比较好的分割结果.

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

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

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

Grabcut 算法的基本步骤:

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),可能是前景

              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         //鼠标响应处理函数的ID,识别号
                     );
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<opencv2\highgui\highgui.hpp>
#include<opencv2\imgproc\imgproc.hpp>
#include<iostream>
#include <opencv2\opencv.hpp>
#include <math.h>
using namespace cv;
using namespace std;

 //grabcut算法
bool setMouse = false;    //判断鼠标左键的状态(up / down)
bool init;
Point pt;
Rect rect;
Mat srcImg, mask, bgModel, fgModel;
int numRun = 0;
void onMouse(int, int, int, int, void*);
void runGrabCut();
void showImage();
int main()
{
	srcImg = imread("tahiti.jpg");
	if (srcImg.empty())
	{
		printf("could not load image...\n");
		return -1;
	}

	imshow("源图像", srcImg);

	mask.create(srcImg.size(), CV_8U);
	setMouseCallback("源图像", onMouse, 0);

	while (1)
	{
		char c = (char)waitKey(0);
		if (c == ' ') {//选中矩形框后,按空格键执行grabcut分割
			runGrabCut();
			numRun++;
			showImage();
			printf("current iteative times : %d\n", numRun);
		}
		if ((int)c == 27) {
			break;
		}

	}
	return 0;
}

void showImage()
{
	Mat result, binmask;
	binmask = mask & 1;				//进一步掩膜
	if (init)						//进一步抠出无效区域。鼠标按下,init变为false
	{
		srcImg.copyTo(result, binmask);
	}
	else
	{
		result = srcImg.clone();
	}
	rectangle(result, rect, Scalar(0, 0, 255), 2, 8);
	imshow("源图像", result);
}

void onMouse(int events, int x, int y, int flag, void *)
{
	if (x < 0 || y < 0 || x > srcImg.cols || y > srcImg.rows)	//无效区域
		return;

	if (events == EVENT_LBUTTONDOWN)
	{
		setMouse = true;
		pt.x = x;
		pt.y = y;
		init = false;
	}
	else if (events == EVENT_MOUSEMOVE)//鼠标只要动,就执行一次
	{
		if (setMouse == true)			//鼠标左键按住,滑动
		{
			Point pt1;
			pt1.x = x;
			pt1.y = y;
			rect = Rect(pt, pt1);//定义矩形区域
			showImage();
			mask.setTo(Scalar::all(GC_BGD));//背景
			mask(rect).setTo(Scalar(GC_PR_FGD));//前景			    //对rect内部设置为可能的前景,外部设置为背景
		}
	}
	else if (events == EVENT_LBUTTONUP)
		setMouse = false;	        	//鼠标左键抬起
}

void runGrabCut()
{
	if (init)//鼠标按下,init变为false
		grabCut(srcImg, mask, rect, bgModel, fgModel, 1);//第二次迭代,用mask初始化grabcut
	else
	{
		grabCut(srcImg, mask, rect, bgModel, fgModel, 1, GC_INIT_WITH_RECT);//用矩形窗初始化GrabCut
		init = true;
	}
}

到此这篇关于OpenCV中Grabcut算法的具体使用的文章就介绍到这了,更多相关OpenCV Grabcut算法内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

(0)

相关推荐

  • python OpenCV GrabCut使用实例解析

    这篇文章主要介绍了python OpenCV GrabCut使用实例解析,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下 先上一个效果图: 使用Python3.7+OpenCV 3.x. 需要引入 numpy库. 在图上用鼠标左键和右键标记前景和后景即可. 如果需要重新标记图像,关闭程序重新运行. 以下是具体实现代码 # -*- coding:utf-8 -*- ''' Python: 3.5.7 opencv 3.x 在图上用鼠标左键和右键标记

  • C++ opencv利用grabCut算法实现抠图示例

    目录 前言 一.grabCut函数 二.compare函数 三.代码 前言 grabCut算法利用了图像中的纹理(颜色)信息和边界(反差)信息,只用少量的用户交互操作,即可得到比较好的分割结果,和分水岭顺丰比较相似,但是计算速度比较慢,得到的结果比较精确 用法:输入一幅图片并对一些像素做属于背景或属于前景的标记,算法会根据这个局部标记计算出整个图像中前景和背景的分割线. 一.grabCut函数 void grabCut(InputArray img, InputOutputArray mask,

  • OpenCV中Grabcut算法的具体使用

    目录 Grabcut 算法的基本步骤: Grabcut的相关API: Grabcut 算法的代码示例: Grabcut 算法主要运用于计算机视觉中的前背景分割,立体视觉和抠图等.该算法利用了图像中的纹理(颜色)信息和边界(反差)信息,只要少量的用户交互操作即可得到比较好的分割结果. 1. Grabcut 的目标和背景的模型是RGB三通道的混合高斯模型GMM; 2. Grab Cut为一个不断进行分割估计和模型参数学习的交互迭代过程: 3. Grab Cut只需要提供背景区域的像素集就可以了.也就

  • openCV中meanshift算法查找目标的实现

    目录 一.简介 二.实现过程 1.设定感兴趣的区域 2.获取脸部直方图并做归一化 3.反向投影,用meanshift查找目标 三.其他实验结果 四.部分原理补充 五.完整代码 一.简介 图像直方图的反向投影是一个概率分布图,表示一个指定图像片段出现在特定位置的概率.当我们已知图像中某个物体的大体位置时,可以通过概率分布图找到物体在另一张图像中的准确位置.我们可以设定一个初始位置,在其周围反复移动来提高局部匹配概率,从而找到物体的准确位置,这个实现过程叫做均值平移算法. 二.实现过程 因为人物的面

  • Opencv中cv2.floodFill算法的使用

    目录 一. 泛洪算法--floodFill函数原型 二.简单应用 三.应用,结合minareaRect 一. 泛洪算法--floodFill函数原型 cv2.floodFill(img,mask,seed,newvalue(BGR),(loDiff1,loDiff2,loDiff3),(upDiff1,upDiff2,upDiff3),flag) img:为待使用泛洪算法的图像 mask:为掩码层,使用掩码可以规定是在哪个区域使用该算法,如果是对于完整图像都要使用,则掩码层大小为原图行数+2,列

  • Opencv基于CamShift算法实现目标跟踪

    CamShift算法全称是"Continuously Adaptive Mean-Shift"(连续的自适应MeanShift算法),是对MeanShift算法的改进算法,可以在跟踪的过程中随着目标大小的变化实时调整搜索窗口大小,对于视频序列中的每一帧还是采用MeanShift来寻找最优迭代结果,至于如何实现自动调整窗口大小的,可以查到的论述较少,我的理解是通过对MeanShift算法中零阶矩的判断实现的. 在MeanShift算法中寻找搜索窗口的质心用到窗口的零阶矩M00和一阶矩M1

  • 利用Opencv中Houghline方法实现直线检测

    利用Opencv中的Houghline方法进行直线检测-python语言 这是给Python部落翻译的文章,请在这里看原文. 在图像处理中,霍夫变换用来检测任意能够用数学公式表达的形状,即使这个形状被破坏或者有点扭曲. 下面我们将看到利用HoughLine算法来阐述霍夫变化进行直线检测的原理,把此算法应用到特点图像的边缘检测是可取的.边缘检测方法请参考这篇文章–边缘检测. Houghline算法基础 直线可以表示为y=mx+c,或者以极坐标形式表示为r=xcosθ+ysinθ,其中r是原点到直线

  • python opencv之SURF算法示例

    本文介绍了python opencv之SURF算法示例,分享给大家,具体如下: 目标: SURF算法基础 opencv总SURF算法的使用 原理: 上节课使用了SIFT算法,当时这种算法效率不高,需要更快速的算法.在06年有人提出了SURF算法"加速稳定特征",从名字上来看,他是SIFT算法的加速版本. (原文) 在SIFT算法当中使用高斯差分方程(Difference of Gaussian)对高斯拉普拉斯方程( Laplacian of Gaussian)进行近似.然而,SURF使

  • python opencv之SIFT算法示例

    本文介绍了python opencv之SIFT算法示例,分享给大家,具体如下: 目标: 学习SIFT算法的概念 学习在图像中查找SIFT关键的和描述符 原理: (原理部分自己找了不少文章,内容中有不少自己理解和整理的东西,为了方便快速理解内容和能够快速理解原理,本文尽量不使用数学公式,仅仅使用文字来描述.本文中有很多引用别人文章的内容,仅供个人记录使用,若有错误,请指正出来,万分感谢) 之前的harris算法和Shi-Tomasi 算法,由于算法原理所致,具有旋转不变性,在目标图片发生旋转时依然

  • python opencv之分水岭算法示例

    本文介绍了python opencv之分水岭算法示例,分享给大家,具体如下: 目标 使用分水岭算法对基于标记的图像进行分割 使用函数cv2.watershed() 原理: 灰度图像可以被看成拓扑平面,灰度值高的区域可以看出山峰,灰度值低的区域可以看成是山谷.向每一个山谷当中灌不同颜色的水.水位升高,不同山谷的水会汇合,为防止不同山谷的水汇合,小在汇合处建立起堤坝.然后继续灌水,然后再建立堤坝,直到山峰都掩模.构建好的堤坝就是图像的分割. 此方法通常会得到过渡分割的结果,因为图像中的噪声以及其他因

  • OpenCV中Canny边缘检测的实现

    目录 1. Canny 边缘检测理论 1.1.高斯滤波 1.2.Sobel算子计算梯度和方向 1.3.非极大值抑制(定位准确的边缘同时可缩小边缘线宽) 1.4.双阈值检测 2. OpenCV 之 Canny 边缘检测 边缘检测一般是识别目标图像中亮度变化明显的像素点. 因为显著变化的像素点通常反映了图像变化比较重要的地方. 1. Canny 边缘检测理论 Canny 是一种常用的边缘检测算法. 其是在 1986 年 John F.Canny 提出的. Canny 是一种 multi-stage

随机推荐