Opencv2 learning 8th days extract separation foreground and background

Source: Internet
Author: User

Grabcut

Code from http://www.cnblogs.com/tornadomeet/archive/2012/11/09/2763271.html

# Include <opencv2/highgui. HPP> # include <opencv2/CORE/core. HPP> # include <vector> # include <iostream> # include <opencv2/imgproc. HPP> // # include ".. /.. /.. /.. /.. /downloads/colourhistogram. H "using namespace STD; using namespace CV; static 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_bg D pixels \ n "\ tshift + right mouse button-set cg_pr_fgd pixels \ n" <Endl;} const scalar Red = scalar (255 ); const scalar pink = scalar (230,130,255); const scalar Blue = scalar (255,255,160, 0); const scalar lightblue = scalar (0,255); const scalar Green = scalar (, 0 ); const int bgd_key = cv_event_flag_ctrlkey; // ctrl key const int fgd_key = cv_event_flag_shiftkey; // Shift key static void getbinmask (const m At & 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; // obtain the signature bit of the mask. In fact, only definite or possible foreground points are retained as mask} 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; vector <point> fgdpxls, bgdpxls, prfgdpxls, prbgdpxls; int itercount ;};/* assign a value to the class variable */void gcapplicati On: reset () {If (! Mask. empty () mask. setto (scalar: All (gc_bgd); bgdpxls. clear (); fgdpxls. clear (); prbgdpxls. clear (); prfgdpxls. clear (); isinitialized = false; rectstate = not_set; // not_set = 0 lblsstate = not_set; prlblsstate = not_set; itercount = 0 ;} /* assign values to the member variables of the class */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 () ;}/ * displays four vertices, a rectangle and image content, this function is used in many subsequent steps, so it is used separately */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); // copy data based on whether the Delimiter is 0 or 1, only images related to the foreground, such as the possible foreground and possible background} vector <point >:: const_iterator it; /* the following code shows the four selected points in different colors */For (IT = bgdpxls. begin (); it! = Bgdpxls. end (); ++ it) // iterator can be seen as a pointer circle (Res, * It, radius, Blue, thickness); For (IT = fgdpxls. begin (); it! = Fgdpxls. end (); ++ it) // The specified foreground uses red to represent 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 ); /* draw a rectangle */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);}/* after this step is completed, the rect inside the mask image is 3, and the outside is all 0 */void gcapplication:: setrectinmask () {assert (! Mask. empty (); mask. setto (gc_bgd); // gc_bgd = 0rect. 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); // gc_pr_fgd = 3, inside the rectangle, possible foreground point} void gcapplication: setlblsinmask (INT flags, point P, bool ispr) {vector <point> * bpxls, * fpxls; uchar bvalue, fvalue; If (! Ispr) // The specified vertex {bpxls = & bgdpxls; fpxls = & fgdpxls; bvalue = gc_bgd; // 0 fvalue = gc_fgd; // 1} else // probability point {bpxls = & prbgdpxls; fpxls = & prfgdpxls; bvalue = gc_pr_bgd; // 2 fvalue = gc_pr_fgd; // 3} If (flags & bgd_key) {bpxls-> push_back (p); Circle (mask, P, radius, bvalue, thickness ); // This point is 2} If (flags & fgd_key) {fpxls-> push_back (p); Circle (mask, P, radius, fvalue, thickness ); // 3}/* mouse response function at this point. The flags parameter is cv_eve. Combination of nt_flag */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) // only when the left button is pressed {rectstate = in_process; // indicates that a rectangle is being painted rect = rect (X, Y, 1, 1 );} if (ISB | ISF) & rectstate = set) // press the alt or shift key and draw a rectangle, indicates that the foreground background is being painted. 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) // draws a possible foreground background point prlblsstate = in_process;} break; Case cv_event_lbuttonup: if (rectstate = in_process) {rect = rect (point (rect. x, rect. y), point (x, y); // rectstate = set at the end of the rectangle; setrectinmask (); Assert (bgdpxls. empty () & fgdpxls. empty () & prbgdpxls. empty () & prfgdpxls. empty (); showimage ();} If (lblsstate = in_process) // you have drawn the front and back attractions {setlblsinmask (flags, point (X, Y ), False); // draw the foreground vertex lblsstate = set; showimage ();} break; Case cv_event_rbuttonup: If (prlblsstate = in_process) {setlblsinmask (flags, point (X, y), true); // draw the background point 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 (); // constant Display image} 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 ;}/ * This function implements the grabcut algorithm, and return the number of iterations of the algorithm operation */INT gcapplication: nextiter () {If (isinitialized) // use grab Algorithm for one iteration. Parameter 2 is mask, the mask bit in it is: Remove all vertices inside the rectangle that may be the background or have been determined as the background, and the mask also saves the split foreground image 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; static 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) {string filename = "D: \ images \ dog.jpg "; 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 ;}

The grabcut method code provided by opencv2 is not easy to implement.

class WatershedSegmenter {private:cv::Mat markers;public:void setMarkers(const cv::Mat& markerImage) {// Convert to image of intsmarkerImage.convertTo(markers,CV_32S);}cv::Mat process(const cv::Mat &image) {// Apply watershedcv::watershed(image,markers);return markers;}// Return result in the form of an imagecv::Mat getSegmentation() {cv::Mat tmp;// all segment with label higher than 255// will be assigned value 255markers.convertTo(tmp,CV_8U);return tmp;}// Return watershed in the form of an imagecv::Mat getWatersheds() {cv::Mat tmp;markers.convertTo(tmp,CV_8U,255,255);return tmp;}};int main(){using namespace cv;// Open another imageMat image= cv::imread("D:\\images\\tower.jpg");// define bounding rectanglecv::Rect rectangle(50,70,image.cols-150,image.rows-180);cv::Mat result; // segmentation result (4 possible values)cv::Mat bgModel,fgModel; // the models (internally used)// GrabCut segmentationcv::grabCut(image,    // input imageresult,   // segmentation resultrectangle,// rectangle containing foregroundbgModel,fgModel, // models1,        // number of iterationscv::GC_INIT_WITH_RECT); // use rectangle// Get the pixels marked as likely foregroundcv::compare(result,cv::GC_PR_FGD,result,cv::CMP_EQ);// Generate output imagecv::Mat foreground(image.size(),CV_8UC3,cv::Scalar(255,255,255));image.copyTo(foreground,result); // bg pixels not copied// draw rectangle on original imagecv::rectangle(image, rectangle, cv::Scalar(255,255,255),1);cv::namedWindow("Image");cv::imshow("Image",image);// display resultcv::namedWindow("Segmented Image");cv::imshow("Segmented Image",foreground);// Open another imageimage= cv::imread("D:\\images\\tower.jpg");// define bounding rectanglecv::Rect rectangle2(10,100,380,180);cv::Mat bkgModel,fgrModel; // the models (internally used)// GrabCut segmentationcv::grabCut(image,  // input imageresult, // segmentation resultrectangle2,bkgModel,fgrModel,5,cv::GC_INIT_WITH_RECT);// Get the pixels marked as likely foreground//      cv::compare(result,cv::GC_PR_FGD,result,cv::CMP_EQ);result= result&1;foreground.create(image.size(),CV_8UC3);foreground.setTo(cv::Scalar(255,255,255));image.copyTo(foreground,result); // bg pixels not copied// draw rectangle on original imagecv::rectangle(image, rectangle2, cv::Scalar(255,255,255),1);cv::namedWindow("Image 2");cv::imshow("Image 2",image);// display resultcv::namedWindow("Foreground objects");cv::imshow("Foreground objects",foreground);waitKey(0);system("pause");return 0;}

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.