#include<iostream> #include <opencv2/opencv.hpp> #include <math.h> using namespace cv; using namespace std; //grabcut算法 bool setMouse = false; //判断鼠标左键的状态(up / down) bool init; Point pt; Rect rect; Mat srcImg, mask, bgModel, fgModel; int numRun = 0; void onm ouse(int, int, int, int, void*); void runGrabCut(); void showImage(); int main() { srcImg = imread("/home/leoxae/KeekoRobot/TestPic/手持卡片/2.png"); if (srcImg.empty()) { printf("could not load image...\n"); return -1; } imshow("源图像", srcImg); mask.create(srcImg.size(), CV_8U); setMouseCallback("源图像", onm ouse, 0); while (1) { char c = (char)waitKey(0); if (c == ' ') {//选中矩形框后,按空格键执行grabcut分割 runGrabCut(); numRun++; showImage(); printf("current iteative times : %d\n", numRun); } if ((int)c == 27) { break; } } return 0; } void showImage() { Mat result, binmask; binmask = mask & 1; //进一步掩膜 if (init) //进一步抠出无效区域。鼠标按下,init变为false { srcImg.copyTo(result, binmask); } else { result = srcImg.clone(); } rectangle(result, rect, Scalar(0, 0, 255), 2, 8); imshow("源图像", result); } void onm ouse(int events, int x, int y, int flag, void *) { if (x < 0 || y < 0 || x > srcImg.cols || y > srcImg.rows) //无效区域 return; if (events == EVENT_LBUTTONDOWN) { setMouse = true; pt.x = x; pt.y = y; init = false; } else if (events == EVENT_MOUSEMOVE)//鼠标只要动,就执行一次 { if (setMouse == true) //鼠标左键按住,滑动 { Point pt1; pt1.x = x; pt1.y = y; rect = Rect(pt, pt1);//定义矩形区域 showImage(); mask.setTo(Scalar::all(GC_BGD));//背景 mask(rect).setTo(Scalar(GC_PR_FGD));//前景 //对rect内部设置为可能的前景,外部设置为背景 } } else if (events == EVENT_LBUTTONUP) setMouse = false; //鼠标左键抬起 } void runGrabCut() { if (init)//鼠标按下,init变为false grabCut(srcImg, mask, rect, bgModel, fgModel, 1);//第二次迭代,用mask初始化grabcut else { grabCut(srcImg, mask, rect, bgModel, fgModel, 1, GC_INIT_WITH_RECT);//用矩形窗初始化GrabCut init = true; } }
运行结果: