Two kinds of image segmentation methods are based on morphological watershed algorithm and Grabcut algorithm based on graph cutting theory. The OPENCV provides two algorithms or variants. In view of the research required, some knowledge points are recorded and the development platform is opencv2.4.9+qt5.3.2.
First, using watershed algorithm for image segmentation
Watershed transformation is a commonly used image processing algorithm, which can be easily searched on the Internet for detailed principle analysis. In short, this is a mathematical morphology based on the topological theory of image segmentation, the basic idea is to view the image as a topological landform, the image of each pixel of the gray value of the point of view of the altitude, each local minimum and its affected area is called the catchment basin, and the basin boundary is formed watershed. The concept and formation of a watershed can be explained by simulating the immersion process. At each local minimum surface, pierce a small hole, then immerse the whole model slowly into the water, with the deepening of immersion, each local minimum of the affected domain slowly outward expansion, at the confluence of two basins to build a dam, that is, the formation of a watershed.
Watershed algorithm is simple, so there are some defects, such as easy to lead to excessive segmentation of images. OPENCV provides an improved version of the algorithm that uses a predefined set of tags to guide the segmentation of an image, which is achieved through the cv::watershed function.
#ifndef Watershedsegmentation_h#define WATERSHEDSEGMENTATION_H#include <opencv2/core/core.hpp>#include <opencv2/highgui/highgui.hpp>#include <opencv2/imgproc/imgproc.hpp> class watershedsegmentation{ Public:voidSetmarkers (ConstCv::mat &markerimage);//Convert the original image to an integer imageCv::mat Process (ConstCv::mat &image);//// watershed algorithm implementation //Below are two special methods for simplifying resultsCv::mat getsegmentation (); Cv::mat getwatersheds ();Private: Cv::mat markers;//For markers that are not 0 pixel points};#endif//Watershedsegmentation_h
#include "Watershedsegmentation.h"#include <Opencv2/core/core.Hpp>#include <Opencv2/highgui/highgui.Hpp>#include <Opencv2/imgproc/imgproc.Hpp>voidWatershedsegmentation:: Setmarkers(CONST CV:: Mat &Markerimage)//Convert the original image to an integer image{Markerimage.ConvertTo (markers,cv_32s);} Cv:: MatWatershedsegmentation::p rocess(CONST CV:: Mat &Image) {//Using watershed algorithmsCv:: Watershed(image,markers);returnmarkers;}//Below are two special methods for simplifying results//Returns the watershed result as an imageCv:: MatWatershedsegmentation:: Getsegmentation() {CV:: Mattmp//All label splits with pixel values above 255 are assigned a value of 255Markers.ConvertTo (tmp,cv_8u);returnTMP;} Cv:: MatWatershedsegmentation:: Getwatersheds() {CV:: Mattmp Markers.ConvertTo (tmp,cv_8u,255,255);returnTMP;}
Main function:
#include <QCoreApplication> #include"Watershedsegmentation.h"#include <opencv2/core/core.hpp> #include <opencv2/highgui/highgui.hpp> #include <opencv2/imgproc/ Imgproc.hpp>intMainintARGC, Char*ARGV[]) {qcoreapplication A (argc, argv);//Read input ImageCv::matImage= Cv::imread ("C:/gray.jpg");if(!Image. Data)return 0;//Display the Image9Cv::namedwindow ("Original Image"); Cv::imshow ("Original Image",Image);//Get the binary mapCv::mat binary; Binary= Cv::imread ("C:/gray.jpg",0);//Display the binary imageCv::namedwindow ("Binary Image"); Cv::imshow ("Binary Image", binary);//RemovalCv::mat FG; Cv::erode (Binary,fg,cv::mat (), CV::P oint (-1,-1),6);//Display the foreground imageCv::namedwindow ("Foreground Image"); Cv::imshow ("Foreground Image", FG);//Identify image pixels without objectsCv::mat BG; CV::d ilate (Binary,bg,cv::mat (), CV::P oint (-1,-1),6); Cv::threshold (BG,BG,1, -, CV::THRESH_BINARY_INV);//Display the background imageCv::namedwindow ("Background Image"); Cv::imshow ("Background Image", BG);//Show markers ImageCv::mat markers (binary.size(), Cv_8u,cv::scalar (0)); Markers= FG+BG; Cv::namedwindow ("Markers"); Cv::imshow ("Markers", markers);//Create Watershed Segmentation ObjectWatershedsegmentation Segmenter;//Set markers and processSegmenter.setmarkers (markers); Segmenter.process (Image);//Display Segmentation resultCv::namedwindow ("Segmentation"); Cv::imshow ("Segmentation", Segmenter.getsegmentation ());//Display watershedsCv::namedwindow ("Watersheds"); Cv::imshow ("Watersheds", Segmenter.getwatersheds ());//Open another image Image= Cv::imread (".. /tower.jpg ");//Identify background pixelsCv::mat Imagemask (Image.size(), Cv_8u,cv::scalar (0)); Cv::rectangle (IMAGEMASK,CV::P oint (5,5), CV::P oint (Image. cols-5,Image. rows-5), Cv::scalar (255),3);//Identify foreground pixels ( in the middle of the image)Cv::rectangle (IMAGEMASK,CV::P oint (Image. cols/2-Ten,Image. rows/2-Ten), CV::P oint (Image. cols/2+Ten,Image. rows/2+Ten), Cv::scalar (1),Ten);//Set markers and processSegmenter.setmarkers (Imagemask); Segmenter.process (Image);//Display the image with markersCv::rectangle (Image, CV::P oint (5,5), CV::P oint (Image. cols-5,Image. rows-5), Cv::scalar (255,255,255),3); Cv::rectangle (Image, CV::P oint (Image. cols/2-Ten,Image. rows/2-Ten), CV::P oint (Image. cols/2+Ten,Image. rows/2+Ten), Cv::scalar (1,1,1),Ten); Cv::namedwindow ("Image with marker"); Cv::imshow ("Image with marker",Image);//Display watershedsCv::namedwindow ("Watersheds of foreground object"); Cv::imshow ("Watersheds of foreground object", Segmenter.getwatersheds ());//Open another image Image= Cv::imread (".. /tower.jpg ");//define bounding rectangleCv::rect Rectangle ( -, -,Image. cols- Max,Image. rows- the); 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,//Models 1,// 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 image Image= Cv::imread (".. /group.jpg ");//define bounding rectangleCv::rect Rectangle2 (Ten, -,380, the); 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);return 0;returnA.exec();}
OpenCV2 Study Notes (iv): Comparison of two image segmentation methods