热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

OpenCV中Grabcut算法的具体使用

本文主要介绍了OpenCV中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
#include
#include
#include 
#include 
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算法内容请搜索以前的文章或继续浏览下面的相关文章希望大家以后多多支持!


推荐阅读
  • 在处理大规模数据数组时,优化分页组件对于提高页面加载速度和用户体验至关重要。本文探讨了如何通过高效的分页策略,减少数据渲染的负担,提升应用性能。具体方法包括懒加载、虚拟滚动和数据预取等技术,这些技术能够显著降低内存占用和提升响应速度。通过实际案例分析,展示了这些优化措施的有效性和可行性。 ... [详细]
  • 本项目通过Python编程实现了一个简单的汇率转换器v1.02。主要内容包括:1. Python的基本语法元素:(1)缩进:用于表示代码的层次结构,是Python中定义程序框架的唯一方式;(2)注释:提供开发者说明信息,不参与实际运行,通常每个代码块添加一个注释;(3)常量和变量:用于存储和操作数据,是程序执行过程中的重要组成部分。此外,项目还涉及了函数定义、用户输入处理和异常捕获等高级特性,以确保程序的健壮性和易用性。 ... [详细]
  • 在 Linux 环境下,多线程编程是实现高效并发处理的重要技术。本文通过具体的实战案例,详细分析了多线程编程的关键技术和常见问题。文章首先介绍了多线程的基本概念和创建方法,然后通过实例代码展示了如何使用 pthreads 库进行线程同步和通信。此外,还探讨了多线程程序中的性能优化技巧和调试方法,为开发者提供了宝贵的实践经验。 ... [详细]
  • 本指南从零开始介绍Scala编程语言的基础知识,重点讲解了Scala解释器REPL(读取-求值-打印-循环)的使用方法。REPL是Scala开发中的重要工具,能够帮助初学者快速理解和实践Scala的基本语法和特性。通过详细的示例和练习,读者将能够熟练掌握Scala的基础概念和编程技巧。 ... [详细]
  • Flutter 2.* 路由管理详解
    本文详细介绍了 Flutter 2.* 中的路由管理机制,包括路由的基本概念、MaterialPageRoute 的使用、Navigator 的操作方法、路由传值、命名路由及其注册、路由钩子等。 ... [详细]
  • 零拷贝技术是提高I/O性能的重要手段,常用于Java NIO、Netty、Kafka等框架中。本文将详细解析零拷贝技术的原理及其应用。 ... [详细]
  • 微信公众号推送模板40036问题
    返回码错误码描述说明40001invalidcredential不合法的调用凭证40002invalidgrant_type不合法的grant_type40003invalidop ... [详细]
  • 本文详细介绍了 PHP 中对象的生命周期、内存管理和魔术方法的使用,包括对象的自动销毁、析构函数的作用以及各种魔术方法的具体应用场景。 ... [详细]
  • 思科IOS XE与ISE集成实现TACACS认证配置
    本文详细介绍了如何在思科IOS XE设备上配置TACACS认证,并通过ISE(Identity Services Engine)进行用户管理和授权。配置包括网络拓扑、设备设置和ISE端的具体步骤。 ... [详细]
  • 开机自启动的几种方式
    0x01快速自启动目录快速启动目录自启动方式源于Windows中的一个目录,这个目录一般叫启动或者Startup。位于该目录下的PE文件会在开机后进行自启动 ... [详细]
  • 本地存储组件实现对IE低版本浏览器的兼容性支持 ... [详细]
  • PHP预处理常量详解:如何定义与使用常量 ... [详细]
  • 本文探讨了使用JavaScript在不同页面间传递参数的技术方法。具体而言,从a.html页面跳转至b.html时,如何携带参数并使b.html替代当前页面显示,而非新开窗口。文中详细介绍了实现这一功能的代码及注释,帮助开发者更好地理解和应用该技术。 ... [详细]
  • 在 Vue 应用开发中,页面状态管理和跨页面数据传递是常见需求。本文将详细介绍 Vue Router 提供的两种有效方式,帮助开发者高效地实现页面间的数据交互与状态同步,同时分享一些最佳实践和注意事项。 ... [详细]
  • 微信小程序实现类似微博的无限回复功能,内置云开发数据库支持
    本文详细介绍了如何利用微信小程序实现类似于微博的无限回复功能,并充分利用了微信云开发的数据库支持。文中不仅提供了关键代码片段,还包含了完整的页面代码,方便开发者按需使用。此外,HTML页面中包含了一些示例图片,开发者可以根据个人喜好进行替换。文章还将展示详细的数据库结构设计,帮助读者更好地理解和实现这一功能。 ... [详细]
author-avatar
聪头丶_505
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有