opencv學習筆記五十八:grabCut摳圖
阿新 • • 發佈:2018-12-11
基本步驟:
- 基於互動式介面由使用者選擇前景區域;
- 定義一個單通道的輸出掩碼,0為背景,1為前景,2為可能的背景,3為可能的前景;
- grabCut摳圖;將輸出結果與可能的前景作比較得到可能的前景;
- 定義三通道的結果影象;
- 從原圖中拷貝可能的前景到結果影象;
grabCut( InputArray img, InputOutputArray mask, Rect rect, InputOutputArray bgdModel, InputOutputArray fgdModel, int iterCount, int mode = GC_EVAL );
img:輸入原影象;
mask:輸出掩碼;
rect:使用者選擇的前景矩形區域;
bgModel:輸出背景影象;
fgModel:輸出前景影象;
iterCount:迭代次數;
#include<opencv2\opencv.hpp> using namespace cv; void onMouse(int event, int x, int y, int flags, void* userdata); Rect rect; Mat src,roiImg, result; void showImg(); int main(int arc, char** argv) { src = imread("3.jpg"); namedWindow("input", CV_WINDOW_AUTOSIZE); imshow("input", src); setMouseCallback("input", onMouse); //定義輸出結果,結果為:GC_BGD =0(背景),GC_FGD =1(前景),GC_PR_BGD = 2(可能的背景), GC_PR_FGD = 3(可能的前景) Mat result = Mat::zeros(src.size(), CV_8UC1); // GrabCut 摳圖 //兩個臨時矩陣變數,作為演算法的中間變數使用 Mat bgModel, fgModel; char c = waitKey(0); if (c == 'g') { grabCut(src, result, rect, bgModel, fgModel, 1, GC_INIT_WITH_RECT); //比較result的值為可能的前景畫素才輸出到result中 compare(result, GC_PR_FGD, result, CMP_EQ); // 產生輸出影象 Mat foreground(src.size(), CV_8UC3, Scalar(255, 255, 255)); //將原影象src中的result區域拷貝到foreground中 src.copyTo(foreground, result); imshow("output", foreground); } waitKey(0); return 0; } void showImg() { src.copyTo(roiImg); rectangle(roiImg, rect, Scalar(0, 0, 255), 2); imshow("input", roiImg); } //滑鼠選擇矩形框 void onMouse(int event, int x, int y, int flags, void* userdata){ switch (event) { case CV_EVENT_LBUTTONDOWN://滑鼠左鍵按下事件 rect.x = x; rect.y = y; rect.width = 1; rect.height = 1; break; case CV_EVENT_MOUSEMOVE://滑鼠移動事件 if (flags && CV_EVENT_FLAG_LBUTTON) { rect = Rect(Point(rect.x, rect.y), Point(x, y)); showImg(); } break; case EVENT_LBUTTONUP://滑鼠彈起事件 if (rect.width > 1 && rect.height > 1) { showImg(); } break; default: break; } }