Learning opencv -- grabcut

Source: Internet
Author: User

 

Grabcut Function Description

Parameters:
  • Image-Input 8-bit 3-channel image.
  • Mask-

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

    • Gc_bgdDefines an obvious background pixels.
    • Gc_fgdDefines an obvious foreground (object) pixel.
    • Gc_pr_bgdDefines a possible background pixel.
    • Gc_pr_bgdDefines 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 shocould make before returning the result. Note that the result can be refined with further callwithMode = gc_init_with_mask
    OrMode = gc_eval.
  • Mode-

    Operation Mode that cocould be one of the following:

    • Gc_init_with_rectThe function initializes the state and the mask using the provided rectangle. After that it runsItercountIterations of the algorithm.
    • Gc_init_with_maskThe function initializes the State using the provided mask. Note thatGc_init_with_rectAnd
      Gc_init_with_maskCan be combined. Then, all the pixels outside of the ROI are automatically initializedGc_bgd.
    • Gc_evalThe value means that the algorithm shoshould just resume.

Function prototype:
Void CV: grabcut (const mat & IMG, mat & Mask, rect,
Mat & bgdmodel, mat & fgdmodel,
Int itercount, int Mode)
Where:
IMG-the source image to be split. It must be an 8-bit, 3-channel (cv_8uc3) image and will not be modified during processing;
Mask: mask image. If mask is used for initialization, the mask stores the initialization mask information. When splitting, you can also save the foreground and background set for user interaction to the mask, then pass in the grabcut function. After processing, the mask will save the result. Mask can only take the following four values:
Gcd_bgd (= 0), background;
Gcd_fgd (= 1), foreground;
Gcd_pr_bgd (= 2), possible background;
Gcd_pr_fgd (= 3), possible prospects.
If gcd_bgd or gcd_fgd is not manually marked, only gcd_pr_bgd or gcd_pr_fgd are displayed;
Rect: used to limit the image range to be split. Only the image part in the rectangle window is processed;
Bgdmodel-background model. If it is null, the function automatically creates a bgdmodel. bgdmodel must be a single-channel floating-point (cv_32fc1) image with only one row and 13x5 columns;
Fgdmodel-foreground model. If it is null, the function automatically creates an fgdmodel. The fgdmodel must be a single-channel floating-point (cv_32fc1) image with only one row and 13x5 columns;
Itercount -- number of iterations, which must be greater than 0;
Mode -- used to indicate the operations performed by the grabcut function. The optional values include:
Gc_init_with_rect (= 0), uses a rectangular window to initialize grabcut;
Gc_init_with_mask (= 1), uses the mask image to initialize grabcut;
Gc_eval (= 2.

 

Opencv built-in code:

#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;}

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

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.