opencv实现图像分割,分离前景和背景(1)

简介  如题,本篇就是讲解和使用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 Rect rect;Mat maskMat bgdModel, fgdModel;rect.rect.rect.rect.Mat& comMask, Mat& binMask ){binMask.CV_8UC1 );binMask argvMat binMask, res;filename image mask.CV_8UC1);mask.setRectInMaskmaskScalarrectanglePointrect.GREENimshow(winName, image);image grabCutGC_INIT_WITH_RECT);getBinMask(mask, binMask);image.imshowres);waitKey

代码讲解  1、首先是装载需要处理的源图片。

filename image

  2、设置掩码,首先创建了一个和源图片一样大小的掩码空间。接着将整个掩码空间设置为背景:GC_BGD。接着创建了一个rect,对应左上角坐标为:(110,220),长宽都为100。接着在掩码空间mask对应左边位置的掩码设置为GC_PR_FGD(疑似为前景)。这个rect就是需要分离前景背景的空间。同时在源图像上,rect对应的需要被处理位置画出绿色方框框选。接着将画了绿色方框之后的源图片显示出来。

mask.CV_8UC1);mask.setRectInMaskmaskScalarrectanglePointrect.GREENimshow(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 NOT_SET IN_PROCESS SET uchar rectState;Rect rect;Mat maskMat bgdModel, fgdModel;rect.rect.rect.rect.rect.image.rect.image.}Mat& comMask, Mat& binMask ){binMask.CV_8UC1 );binMask xflagsMat res;Mat binMask;CV_EVENT_LBUTTONDOWNrectState == NOT_SET){rectState = IN_PROCESS;rect CV_EVENT_LBUTTONUPrectState == IN_PROCESS ){rect PointrectState .image grabCutGC_INIT_WITH_RECT);getBinMask( mask, binMask );image.imshowresCV_EVENT_MOUSEMOVErectState == IN_PROCESS ){rect Pointimage rectanglePointrect.GREENimshowargvfilename image imshow(winName, image);mask.CV_8UC1);rectState = NOT_SET;mask.setMouseCallbackwaitKey

代码讲解  这一步中,主要也就是加入了鼠标响应。通过鼠标左键按下拖动,来框选之前提到的绿色目标框,当释放掉鼠标左键之后,便会将框选的位置进行背景分离。代码下载路径:

而不去欣赏今天就开在我们窗口的玫瑰。

opencv实现图像分割,分离前景和背景(1)

相关文章:

你感兴趣的文章:

标签云: