代碼:
#include<opencv2/opencv.hpp>
bool selectObject = false;
cv::Point origin;
cv::Rect selection;
cv::Mat src;
cv::Mat srcMarks;
cv::Mat result;
cv::Mat foreground;
void GrabCutSegment();
void onMouse(int event, int x, int y, int, void*)
{
if (selectObject)
{
selection.x = MIN(x, origin.x);
selection.y = MIN(y, origin.y);
selection.width = std::abs(x - origin.x);
selection.height = std::abs(y - origin.y);
selection &= cv::Rect(0, 0, src.cols, src.rows);
}
switch (event)
{
case cv::EVENT_LBUTTONDOWN:
origin = cv::Point(x, y);
selection = cv::Rect(x, y, 0, 0);
selectObject = true;
break;
case cv::EVENT_LBUTTONDOWN && cv::EVENT_MOUSEMOVE:
src.copyTo(srcMarks);
cv::rectangle(srcMarks, selection, cv::Scalar(255, 0, 0));
imshow("srcMarks", srcMarks);
break;
case cv::EVENT_LBUTTONUP:
selectObject = false;
if (selection.width != 0 && selection.height != 0){
GrabCutSegment();
}
break;
}
}
void GrabCutSegment(){
cv::Mat bgModel, fgModel;
cv::grabCut(src, result, selection, bgModel, fgModel, 5, cv::GC_INIT_WITH_RECT);
cv::compare(result, cv::GC_PR_FGD, result, cv::CMP_EQ);
// Generate output image
foreground = cv::Mat::ones(src.size(), CV_8UC3);
src.copyTo(foreground, result); // bg pixels not copied
cv::imshow("segment", foreground);
}
int main(){
src = cv::imread("hui.png");
cv::namedWindow("src",CV_WINDOW_NORMAL);
cv::imshow("src", src);
cv::namedWindow("srcMarks",CV_WINDOW_NORMAL);
src.copyTo(srcMarks);
cv::setMouseCallback("srcMarks", onMouse, 0);
cv::imshow("srcMarks", srcMarks);
cv::waitKey();
}
對不同顏色格式圖片分割初步結果:
第一次對灰度圖像處理的結果(原圖無法處理,原因瞭解中,可能圖像過大)
對hsv圖像進行處理:(與灰度圖像相比邊緣更爲整齊,效果更好。會進一步瞭解算法原理)
對二次對灰度圖處理(明顯比第一次好,可見手動選擇矩形區域的重要性,最終目的想要省去交互的這一步,希望更加精確的自動確定目標區域並用grabcut分割)