首页 > MachineLearning > OpenCV实现简单的图像分割

OpenCV实现简单的图像分割

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),执行分割。
  
  难点记录:为什么要用getBinMask重新生成一个binMask?
  grabCut把mask上面rect以外的设置掩码为0,rect范围内的进行预测,每一个像素值设置0、1、2、3这四种值的一种。然后把可能的背景设置为背景(2–>0),把可能的前景设置为前景(3–>1)。然后在Mask应用到图片上。
  下面是可以运行的代码,看懂了之后,我给加了详细的注释

#include "opencv2/highgui/highgui.hpp"
#include "opencv2/imgproc/imgproc.hpp"

#include <iostream>

using namespace std;
using namespace cv;

//自己本地的图片
string filename = "3.jpg";
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;

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 );
                // 用鼠标画一个框
         Point temp(rect.x + rect.width, rect.y + rect.height );
                rectangle(image, Point( rect.x, rect.y ), temp, GREEN, 2);
                imshow(winName, image);
            }
            break;
    }
}

int main(int argc, char* argv[]){
    // 加载并显示图片
    image = imread( filename, 1 );
    imshow(winName, image);
    // 设置掩码,首先创建了一个和源图片一样大小的掩码空间。
    mask.create(image.size(), CV_8UC1);
    // 接着将整个掩码空间设置为背景:GC_BGD。
    mask.setTo(GC_BGD);
    rectState = NOT_SET;
    setMouseCallback(winName, on_mouse, 0);
    waitKey(0);
    return 0;
}

参考资料:
http://lib.csdn.net/article/opencv/28846
http://docs.opencv.org/master/d7/d1b/group__imgproc__misc.html#ga909c1dda50efcbeaa3ce126be862b37f

转载请注明: 转载自阿凡树的博客

本文链接地址: OpenCV实现简单的图像分割

  1. 还没有评论
评论提交中, 请稍候...

留言

可以使用的标签: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>
Trackbacks & Pingbacks ( 0 )
  1. 还没有 trackbacks