OpenCV3.2图像分割 实例8:Grabcut原理与演示应用

发布时间 2023-08-18 09:05:23作者: 一杯清酒邀明月
  1 #include <opencv2/opencv.hpp>
  2 #include <iostream>
  3 #include <math.h>
  4  
  5 using namespace cv;
  6 using namespace std;
  7  
  8 int numRun = 0;
  9 Rect rect;
 10 bool init = false;
 11 Mat src, image;
 12 Mat mask, bgModel, fgModel;//mask,背景,前景
 13 const char* winTitle = "input image";
 14  
 15 void onMouse(int event, int x, int y, int flags, void* param);
 16 void setROIMask();
 17 void showImage();
 18 void runGrabCut();
 19 int main(int argc, char** argv) {
 20     src = imread("tx.png", 1);
 21     if (src.empty()) {
 22         printf("could not load image...\n");
 23         return -1;
 24     }
 25     mask.create(src.size(), CV_8UC1);
 26     mask.setTo(Scalar::all(GC_BGD));
 27  
 28     namedWindow(winTitle, CV_WINDOW_AUTOSIZE);//
 29     setMouseCallback(winTitle, onMouse, 0);//设置鼠标反馈事件
 30     imshow(winTitle, src);
 31  
 32     while (true) {
 33         char c = (char)waitKey(0);
 34         if (c == 'n') {
 35             runGrabCut();//运行GrabCut算法
 36             numRun++;
 37             showImage();
 38             printf("current iteative times : %d\n", numRun);//当前迭代次数
 39         }
 40         if ((int)c == 27) {
 41             break;
 42         }
 43     }
 44  
 45     waitKey(0);
 46     return 0;
 47 }
 48  
 49 void showImage() {
 50     Mat result, binMask;
 51     binMask.create(mask.size(), CV_8UC1);
 52     binMask = mask & 1;
 53     if (init) {
 54         src.copyTo(result, binMask);
 55     } else {
 56         src.copyTo(result);//将src图像拷贝到result中
 57     }
 58     imwrite("tx2.png",result);
 59     rectangle(result, rect, Scalar(0, 0, 255), 2, 8);//在result上绘制红色矩形框rect
 60     imshow(winTitle, result);
 61 }
 62  
 63 void setROIMask() {
 64     // GC_FGD = 1
 65     // GC_BGD =0;
 66     // GC_PR_FGD = 3
 67     // GC_PR_BGD = 2
 68     mask.setTo(GC_BGD);
 69     rect.x = max(0, rect.x);
 70     rect.y = max(0, rect.y);
 71     rect.width = min(rect.width, src.cols - rect.x);
 72     rect.height = min(rect.height, src.rows - rect.y);
 73     mask(rect).setTo(Scalar(GC_PR_FGD));
 74 }
 75  
 76 //鼠标事件函数
 77 void onMouse(int event, int x, int y, int flags, void* param) {
 78     switch (event)
 79     {
 80     case EVENT_LBUTTONDOWN://鼠标左键按下
 81         rect.x = x;//矩形左上角x,y坐标
 82         rect.y = y;
 83         rect.width = 1;//矩形线条宽度、高度
 84         rect.height = 1;
 85         init = false;
 86         numRun = 0;
 87         break;
 88     case EVENT_MOUSEMOVE://鼠标移动
 89         if (flags & EVENT_FLAG_LBUTTON) {
 90             rect = Rect(Point(rect.x, rect.y), Point(x, y));
 91             showImage();//显示带矩形框的图像
 92         }
 93         break;
 94     case EVENT_LBUTTONUP://鼠标左键松开
 95         if (rect.width > 1 && rect.height > 1) {
 96             setROIMask();
 97             showImage();
 98         }
 99         break;
100     default:
101         break;
102     }
103 }
104  
105 //运行GrabCut函数
106 void runGrabCut() {
107     if (rect.width < 2 || rect.height < 2) {
108         return;
109     }
110     
111     if (init) {
112         grabCut(src, mask, rect, bgModel, fgModel, 1);
113     } {
114         grabCut(src, mask, rect, bgModel, fgModel, 1, GC_INIT_WITH_RECT);
115         init = true;
116     }
117 }