opencv实现图像分割,分离前景和背景(1)
来源:互联网 发布:继承在编程方面翻译为 编辑:程序博客网 时间:2024/04/29 10:56
简介
如题,本篇就是讲解和使用opencv函数grabcut,来实现图像前景与背景的分离。
函数原型
1、opencv官方介绍:opencv官方grabcut介绍 2、网上童鞋翻译解释:学习OpenCV——学习grabcut算法 3、大致内容如下: 函数原型: void grabCut(InputArray img, InputOutputArray mask, Rect rect, InputOutputArray bgdModel, InputOutputArray fgdModel, int iterCount, int mode=GC_EVAL ) img:待分割的源图像,必须是8位3通道(CV_8UC3)图像,在处理的过程中不会被修改; mask:掩码图像,大小和原图像一致。可以有如下几种取值: GC_BGD(=0),背景; GC_FGD(=1),前景; GC_PR_BGD(=2),可能的背景; GC_PR_FGD(=3),可能的前景。 rect:用于限定需要进行分割的图像范围,只有该矩形窗口内的图像部分才被处理; bgdModel:背景模型,如果为null,函数内部会自动创建一个bgdModel; fgdModel:前景模型,如果为null,函数内部会自动创建一个fgdModel; iterCount:迭代次数,必须大于0; mode:用于指示grabCut函数进行什么操作。可以有如下几种选择: GC_INIT_WITH_RECT(=0),用矩形窗初始化GrabCut; GC_INIT_WITH_MASK(=1),用掩码图像初始化GrabCut; GC_EVAL(=2),执行分割。
4、基本原理: 首先用户在图片上画一个方框,grabCut默认方框内部为前景,设置掩码为2,方框外部都是背景,设置掩码为0。然后根据算法, 将方框内部检查出来是背景的位置,掩码由2改为0。最后,经过算法处理,方框中掩码依然为2的,就是检查出来的前景,其他为背景。
实例讲解1
这些例子都主要是根据opencv自带的例子:opencv\samples\cpp\grabcut.cpp 简化修改而来。
源代码
代码如下:
#include "opencv2/highgui/highgui.hpp" #include "opencv2/imgproc/imgproc.hpp" #include <iostream> using namespace std;using namespace cv; string filename;Mat image;string winName = "show";Rect rect;Mat mask;const Scalar GREEN = Scalar(0,255,0);Mat bgdModel, fgdModel; void setRectInMask(){rect.x = 110;rect.y = 220;rect.width = 100;rect.height = 100;} static void getBinMask( const Mat& comMask, Mat& binMask ){binMask.create( comMask.size(), CV_8UC1 );binMask = comMask & 1;} int main(int argc, char* argv[]){Mat binMask, res;filename = argv[1];image = imread( filename, 1 );mask.create(image.size(), CV_8UC1);mask.setTo(GC_BGD);setRectInMask();(mask(rect)).setTo(Scalar(GC_PR_FGD));rectangle(image, Point(rect.x, rect.y), Point(rect.x + rect.width, rect.y + rect.height ), GREEN, 2);imshow(winName, image);image = imread( filename, 1 );grabCut(image, mask, rect, bgdModel, fgdModel, 1, GC_INIT_WITH_RECT);getBinMask(mask, binMask);image.copyTo(res, binMask);imshow("result", res); waitKey(0); return 0;}
代码讲解
1、首先是装载需要处理的源图片。
filename = argv[1];image = imread( filename, 1 );
2、设置掩码,首先创建了一个和源图片一样大小的掩码空间。接着将整个掩码空间设置为背景:GC_BGD。接着创建了一个rect,对应左上角坐标为:(110,220),长宽都为100。接着在掩码空间mask对应左边位置的掩码设置为GC_PR_FGD(疑似为前景)。这个rect就是需要分离前景背景的空间。同时在源图像上,rect对应的需要被处理位置画出绿色方框框选。接着将画了绿色方框之后的源图片显示出来。
mask.create(image.size(), CV_8UC1);mask.setTo(GC_BGD);setRectInMask();(mask(rect)).setTo(Scalar(GC_PR_FGD));rectangle(image, Point(rect.x, rect.y), Point(rect.x + rect.width, rect.y + rect.height ), GREEN, 2);imshow(winName, image);
3、之前的源图像被画了绿色方框,所以需要重新装载一遍源图像。接着使用函数grabCut,根据传入的相关参数,进行前景背景分离操作。最后在生成的结果保存在mask中,背景被置为0,前景被置为1。接着将mask结果筛选到binMask中。最后使用image.copyTo(res, binMask);将原图像根据binMask作为掩码,将筛选出来的前景复制到目标图像res中。并将目标图像显示出来。
效果演示
原图像:
目标图像:
实例讲解2
继续这个例子中加入了鼠标的操作。
源代码
#include "opencv2/highgui/highgui.hpp" #include "opencv2/imgproc/imgproc.hpp" #include <iostream> using namespace std;using namespace cv; string filename;Mat image;string winName = "show";enum{NOT_SET = 0, IN_PROCESS = 1, SET = 2};uchar rectState;Rect rect;Mat mask;const Scalar GREEN = Scalar(0,255,0);Mat bgdModel, fgdModel; void setRectInMask(){rect.x = max(0, rect.x);rect.y = max(0, rect.y);rect.width = min(rect.width, image.cols-rect.x);rect.height = min(rect.height, image.rows-rect.y); } static void getBinMask( const Mat& comMask, Mat& binMask ){binMask.create( comMask.size(), CV_8UC1 );binMask = comMask & 1;} void on_mouse( int event, int x, int y, int flags, void* ){Mat res;Mat binMask; switch( event ){case CV_EVENT_LBUTTONDOWN:if( rectState == NOT_SET){rectState = IN_PROCESS;rect = Rect( x, y, 1, 1 );}break;case CV_EVENT_LBUTTONUP:if( rectState == IN_PROCESS ){rect = Rect( Point(rect.x, rect.y), Point(x,y) );rectState = SET;(mask(rect)).setTo( Scalar(GC_PR_FGD));image = imread( filename, 1 );grabCut(image, mask, rect, bgdModel, fgdModel, 1, GC_INIT_WITH_RECT);getBinMask( mask, binMask );image.copyTo(res, binMask );imshow("11", res);}break;case CV_EVENT_MOUSEMOVE:if( rectState == IN_PROCESS ){rect = Rect( Point(rect.x, rect.y), Point(x,y) );image = imread( filename, 1 );rectangle(image, Point( rect.x, rect.y ), Point(rect.x + rect.width, rect.y + rect.height ), GREEN, 2);imshow(winName, image);}break;}} int main(int argc, char* argv[]){filename = argv[1];image = imread( filename, 1 );imshow(winName, image);mask.create(image.size(), CV_8UC1);rectState = NOT_SET;mask.setTo(GC_BGD); setMouseCallback(winName, on_mouse, 0);waitKey(0); return 0;}
代码讲解
这一步中,主要也就是加入了鼠标响应。通过鼠标左键按下拖动,来框选之前提到的绿色目标框,当释放掉鼠标左键之后,便会将框选的位置进行背景分离。
代码下载路径:http://download.csdn.net/detail/u011630458/8700335
1 0
- opencv实现图像分割,分离前景和背景(1)
- opencv实现图像分割,分离前景和背景(2)
- OpenCVForUnity 图像分割,分离前景和背景
- 利用OpenCV的Grabcut()函数实现图像的前景与背景的分割-并对Grabcut()作详细介绍
- OpenCV实现图像物体轮廓,前景背景,标记,并保存。
- 第九章 – 图像局部与分割 – 背景场景和分割前景目标的方法(平均背景法)(例程待实现)
- 分享 Matlab实现视频图像前景分割
- 【OpenCV】5th-识别背景和前景
- Opencv 利用分割的图像掩膜来完善检测前景
- OpenCV3.0 Examples学习笔记(10)-grabcut.cpp-grabcut函数实现人机交互高效分割图像前景背景
- opencv2 学习第8天 提取分离前景和背景
- Halcon代码实现背景减除法获取运动图像前景
- 利用OpenCV实现图像的阈值分割
- opencv之金字塔实现图像分割
- opencv之分水岭实现图像分割
- opencv用金字塔cvPyrSegmentation实现图像分割
- OpenCV学习 kmeans实现图像分割
- 前景背景分离方法(一) 帧差法
- 处理表重复记录(查询和删除)
- 接入D+ 迎接互联网移动端巨变!
- XAAR128/200dpi
- 版本控制(5)--Git简介和仓库创建
- fsck命令一定要慎用
- opencv实现图像分割,分离前景和背景(1)
- java 的DBHelper类型
- 创建Access数据的ODBC数据源时没有Access数据源驱动器
- junit4单元测试报错解决
- IOS UITabBar-持续更新
- xfire配置webService的方法步骤
- 欧拉回路、欧拉路径
- VS2008中定位代码前一个大括号的方法
- 微商快速有效获得精准粉丝的技巧分析