学习OpenCV——grabcut

来源:互联网 发布:中国足球 知乎 编辑:程序博客网 时间:2024/05/17 01:35

 

GrabCut函数说明

Parameters:

  • image – Input 8-bit 3-channel image.
  • mask

    Input/output 8-bit single-channel mask. The mask is initialized by the function whenmode is set toGC_INIT_WITH_RECT. Its elements may have one of following values:

    • GC_BGD defines an obvious background pixels.
    • GC_FGD defines an obvious foreground (object) pixel.
    • GC_PR_BGD defines a possible background pixel.
    • GC_PR_BGD defines a possible foreground pixel.
  • rect – ROI containing a segmented object. The pixels outside of the ROI are marked as “obvious background”. The parameter is only used whenmode==GC_INIT_WITH_RECT .
  • bgdModel – Temporary array for the background model. Do not modify it while you are processing the same image.
  • fgdModel – Temporary arrays for the foreground model. Do not modify it while you are processing the same image.
  • iterCount – Number of iterations the algorithm should make before returning the result. Note that the result can be refined with further calls withmode==GC_INIT_WITH_MASK ormode==GC_EVAL .
  • mode

    Operation mode that could be one of the following:

    • GC_INIT_WITH_RECT The function initializes the state and the mask using the provided rectangle. After that it runsiterCount iterations of the algorithm.
    • GC_INIT_WITH_MASK The function initializes the state using the provided mask. Note thatGC_INIT_WITH_RECT andGC_INIT_WITH_MASK can be combined. Then, all the pixels outside of the ROI are automatically initialized withGC_BGD .
    • GC_EVAL The value means that the algorithm should just resume.

函数原型:
    void cv::grabCut( const Mat& img, Mat& mask, Rect rect,
             Mat& bgdModel, Mat& fgdModel,
             int iterCount, int mode )
其中:
img——待分割的源图像,必须是8位3通道(CV_8UC3)图像,在处理的过程中不会被修改;
mask——掩码图像,如果使用掩码进行初始化,那么mask保存初始化掩码信息;在执行分割的时候,也可以将用户交互所设定的前景与背景保存到mask中,然后再传入grabCut函数;在处理结束之后,mask中会保存结果。mask只能取以下四种值:
GCD_BGD(=0),背景;
GCD_FGD(=1),前景;
GCD_PR_BGD(=2),可能的背景;
GCD_PR_FGD(=3),可能的前景。
如果没有手工标记GCD_BGD或者GCD_FGD,那么结果只会有GCD_PR_BGD或GCD_PR_FGD;
rect——用于限定需要进行分割的图像范围,只有该矩形窗口内的图像部分才被处理;
bgdModel——背景模型,如果为null,函数内部会自动创建一个bgdModel;bgdModel必须是单通道浮点型(CV_32FC1)图像,且行数只能为1,列数只能为13x5;
fgdModel——前景模型,如果为null,函数内部会自动创建一个fgdModel;fgdModel必须是单通道浮点型(CV_32FC1)图像,且行数只能为1,列数只能为13x5;
iterCount——迭代次数,必须大于0;
mode——用于指示grabCut函数进行什么操作,可选的值有:
GC_INIT_WITH_RECT(=0),用矩形窗初始化GrabCut;
GC_INIT_WITH_MASK(=1),用掩码图像初始化GrabCut;
GC_EVAL(=2),执行分割。

 

OpenCV自带的代码:

#include "opencv2/highgui/highgui.hpp"#include "opencv2/imgproc/imgproc.hpp"#include <iostream>using namespace std;using namespace cv;void help(){cout << "\nThis program demonstrates GrabCut segmentation -- select an object in a region\n""and then grabcut will attempt to segment it out.\n""Call:\n""./grabcut <image_name>\n""\nSelect a rectangular area around the object you want to segment\n" <<"\nHot keys: \n""\tESC - quit the program\n""\tr - restore the original image\n""\tn - next iteration\n""\n""\tleft mouse button - set rectangle\n""\n""\tCTRL+left mouse button - set GC_BGD pixels\n""\tSHIFT+left mouse button - set CG_FGD pixels\n""\n""\tCTRL+right mouse button - set GC_PR_BGD pixels\n""\tSHIFT+right mouse button - set CG_PR_FGD pixels\n" << endl;}const Scalar RED = Scalar(0,0,255);const Scalar PINK = Scalar(230,130,255);const Scalar BLUE = Scalar(255,0,0);const Scalar LIGHTBLUE = Scalar(255,255,160);const Scalar GREEN = Scalar(0,255,0);const int BGD_KEY = CV_EVENT_FLAG_CTRLKEY;const int FGD_KEY = CV_EVENT_FLAG_SHIFTKEY;void getBinMask( const Mat& comMask, Mat& binMask ){if( comMask.empty() || comMask.type()!=CV_8UC1 )CV_Error( CV_StsBadArg, "comMask is empty or has incorrect type (not CV_8UC1)" );if( binMask.empty() || binMask.rows!=comMask.rows || binMask.cols!=comMask.cols )binMask.create( comMask.size(), CV_8UC1 );binMask = comMask & 1;}class GCApplication{public:enum{ NOT_SET = 0, IN_PROCESS = 1, SET = 2 };static const int radius = 2;static const int thickness = -1;void reset();void setImageAndWinName( const Mat& _image, const string& _winName );void showImage() const;void mouseClick( int event, int x, int y, int flags, void* param );int nextIter();int getIterCount() const { return iterCount; }private:void setRectInMask();void setLblsInMask( int flags, Point p, bool isPr );const string* winName;const Mat* image;Mat mask;Mat bgdModel, fgdModel;uchar rectState, lblsState, prLblsState;bool isInitialized;Rect rect;vector<Point> fgdPxls, bgdPxls, prFgdPxls, prBgdPxls;int iterCount;};void GCApplication::reset(){if( !mask.empty() )mask.setTo(Scalar::all(GC_BGD));bgdPxls.clear(); fgdPxls.clear();prBgdPxls.clear();  prFgdPxls.clear();isInitialized = false;rectState = NOT_SET;lblsState = NOT_SET;prLblsState = NOT_SET;iterCount = 0;}void GCApplication::setImageAndWinName( const Mat& _image, const string& _winName  ){if( _image.empty() || _winName.empty() )return;image = &_image;winName = &_winName;mask.create( image->size(), CV_8UC1);reset();}void GCApplication::showImage() const{if( image->empty() || winName->empty() )return;Mat res;Mat binMask;if( !isInitialized )image->copyTo( res );else{getBinMask( mask, binMask );image->copyTo( res, binMask );}vector<Point>::const_iterator it;for( it = bgdPxls.begin(); it != bgdPxls.end(); ++it )circle( res, *it, radius, BLUE, thickness );for( it = fgdPxls.begin(); it != fgdPxls.end(); ++it )circle( res, *it, radius, RED, thickness );for( it = prBgdPxls.begin(); it != prBgdPxls.end(); ++it )circle( res, *it, radius, LIGHTBLUE, thickness );for( it = prFgdPxls.begin(); it != prFgdPxls.end(); ++it )circle( res, *it, radius, PINK, thickness );if( rectState == IN_PROCESS || rectState == SET )rectangle( res, Point( rect.x, rect.y ), Point(rect.x + rect.width, rect.y + rect.height ), GREEN, 2);imshow( *winName, res );}void GCApplication::setRectInMask(){assert( !mask.empty() );mask.setTo( GC_BGD );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);(mask(rect)).setTo( Scalar(GC_PR_FGD) );}void GCApplication::setLblsInMask( int flags, Point p, bool isPr ){vector<Point> *bpxls, *fpxls;uchar bvalue, fvalue;if( !isPr ){bpxls = &bgdPxls;fpxls = &fgdPxls;bvalue = GC_BGD;fvalue = GC_FGD;}else{bpxls = &prBgdPxls;fpxls = &prFgdPxls;bvalue = GC_PR_BGD;fvalue = GC_PR_FGD;}if( flags & BGD_KEY ){bpxls->push_back(p);circle( mask, p, radius, bvalue, thickness );}if( flags & FGD_KEY ){fpxls->push_back(p);circle( mask, p, radius, fvalue, thickness );}}void GCApplication::mouseClick( int event, int x, int y, int flags, void* ){// TODO add bad args checkswitch( event ){case CV_EVENT_LBUTTONDOWN: // set rect or GC_BGD(GC_FGD) labels{bool isb = (flags & BGD_KEY) != 0,isf = (flags & FGD_KEY) != 0;if( rectState == NOT_SET && !isb && !isf ){rectState = IN_PROCESS;rect = Rect( x, y, 1, 1 );}if ( (isb || isf) && rectState == SET )lblsState = IN_PROCESS;}break;case CV_EVENT_RBUTTONDOWN: // set GC_PR_BGD(GC_PR_FGD) labels{bool isb = (flags & BGD_KEY) != 0,isf = (flags & FGD_KEY) != 0;if ( (isb || isf) && rectState == SET )prLblsState = IN_PROCESS;}break;case CV_EVENT_LBUTTONUP:if( rectState == IN_PROCESS ){rect = Rect( Point(rect.x, rect.y), Point(x,y) );rectState = SET;setRectInMask();assert( bgdPxls.empty() && fgdPxls.empty() && prBgdPxls.empty() && prFgdPxls.empty() );showImage();}if( lblsState == IN_PROCESS ){setLblsInMask(flags, Point(x,y), false);lblsState = SET;showImage();}break;case CV_EVENT_RBUTTONUP:if( prLblsState == IN_PROCESS ){setLblsInMask(flags, Point(x,y), true);prLblsState = SET;showImage();}break;case CV_EVENT_MOUSEMOVE:if( rectState == IN_PROCESS ){rect = Rect( Point(rect.x, rect.y), Point(x,y) );assert( bgdPxls.empty() && fgdPxls.empty() && prBgdPxls.empty() && prFgdPxls.empty() );showImage();}else if( lblsState == IN_PROCESS ){setLblsInMask(flags, Point(x,y), false);showImage();}else if( prLblsState == IN_PROCESS ){setLblsInMask(flags, Point(x,y), true);showImage();}break;}}int GCApplication::nextIter(){if( isInitialized )grabCut( *image, mask, rect, bgdModel, fgdModel, 1 );else{if( rectState != SET )return iterCount;if( lblsState == SET || prLblsState == SET )grabCut( *image, mask, rect, bgdModel, fgdModel, 1, GC_INIT_WITH_MASK );elsegrabCut( *image, mask, rect, bgdModel, fgdModel, 1, GC_INIT_WITH_RECT );isInitialized = true;}iterCount++;bgdPxls.clear(); fgdPxls.clear();prBgdPxls.clear(); prFgdPxls.clear();return iterCount;}GCApplication gcapp;void on_mouse( int event, int x, int y, int flags, void* param ){gcapp.mouseClick( event, x, y, flags, param );}int main( int argc, char** argv ){if( argc!=2 ){help();return 1;}string filename = argv[1];if( filename.empty() ){cout << "\nDurn, couldn't read in " << argv[1] << endl;return 1;}Mat image = imread( filename, 1 );if( image.empty() ){cout << "\n Durn, couldn't read image filename " << filename << endl;return 1;}help();const string winName = "image";cvNamedWindow( winName.c_str(), CV_WINDOW_AUTOSIZE );cvSetMouseCallback( winName.c_str(), on_mouse, 0 );gcapp.setImageAndWinName( image, winName );gcapp.showImage();for(;;){int c = cvWaitKey(0);switch( (char) c ){case '\x1b':cout << "Exiting ..." << endl;goto exit_main;case 'r':cout << endl;gcapp.reset();gcapp.showImage();break;case 'n':int iterCount = gcapp.getIterCount();cout << "<" << iterCount << "... ";int newIterCount = gcapp.nextIter();if( newIterCount > iterCount ){gcapp.showImage();cout << iterCount << ">" << endl;}elsecout << "rect must be determined>" << endl;break;}}exit_main:cvDestroyWindow( winName.c_str() );return 0;}


参考: http://www.cnblogs.com/xrwang/archive/2010/04/27/GrabCut.html

原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 c1证到期了换证怎么办 驾驶证扣分了3分怎么办 驾驶证脱审4个月怎么办 杭州驾照过期1年怎么办 驾驶证过期5个月怎么办 驾驶证过期3年了怎么办 c驾驶证换证过期怎么办 驾驶证过了两年怎么办 驾驶证过期8个月怎么办 学驾照快过期了怎么办 朋友开我车撞了怎么办 b2驾照扣分没审怎么办 驾驶证脱审2个月怎么办 驾驶证脱审1月怎么办 驾照过期了没换怎么办 驾照过期1年多了怎么办 考驾照科目一考不过怎么办 我考驾照过期了怎么办 驾照过了审验期怎么办 驾照过期3年了怎么办 如果学车过期了怎么办 行驶证过期了3年怎么办 行驶证过期没审怎么办 行驶证过期两年怎么办 驾驶证过期7年了怎么办 换驾照过一个月怎么办? 行驶证正本掉了怎么办 车的行驶证丢了怎么办 三星s6 屏幕坏了怎么办 手机摔成黑屏了怎么办 三星屏幕漏液了怎么办 三星s8屏幕漏液怎么办 屏幕紫色漏液了怎么办 华为手机屏碎了怎么办 小米2s按键失灵怎么办 魅蓝屏幕摔花了怎么办 小米手机屏碎了怎么办 厦门医保卡坏了怎么办 医保卡丢了北京怎么办 重庆社保卡丢了怎么办 沈阳医保卡丢了怎么办