一、分析
貼出應用圖片以供直觀了解
紅色部分,因圖而異(某些參數,根據圖片的不同需要進行相應的修改)
二、代碼
1 #include "opencv2/opencv.hpp" 2 #include<iostream> 3 using namespace cv; 4 using namespace std; 5 6 void main(){ 7 Mat img=imread("E://9.jpg"); 8 int thres_min=220; //二值化最小閾值 9 if(!img.empty()){ 10 //二值化 11 threshold(img, img, thres_min, 255, THRESH_BINARY); 12 imshow("img_thres",img); 13 //img備份 14 Mat copy=img.clone();//拷貝原圖,且不會隨着原圖改變 15 cvtColor(copy,copy,CV_BGR2GRAY);//彩色圖轉灰度圖 16 threshold(copy, copy, thres_min, 255, THRESH_BINARY_INV);//反轉:白色變黑色,黑色變白色 17 imshow("copy", copy); 18 //查找copy的輪廓 19 vector<vector<Point>>contours; 20 findContours(copy, contours, CV_RETR_EXTERNAL, CV_CHAIN_APPROX_SIMPLE); 21 //將輪廓畫在全黑圖像上 22 Mat draw; 23 draw = Mat::zeros(img.size(), CV_32FC1);//定義一個img大小的全黑圖像 24 drawContours(draw, contours, 0, Scalar(255), -2); 25 imshow("img2", draw); 26 //進行膨脹腐蝕操作 27 Mat dilated, eroded; 28 Mat kernel=getStructuringElement(MORPH_RECT,Size(19,19));//定義結構元素 29 dilate(draw, dilated, kernel, Point(-1,-1), 2);//膨脹兩次 30 imshow("dilate", dilated); 31 erode(dilated, eroded, kernel, Point(-1,-1), 2); 32 imshow("erode", eroded); 33 //膨脹腐蝕相減 34 Mat diff; 35 absdiff(dilated, eroded, diff); 36 diff.convertTo(diff, CV_8UC1);//轉換為單通道圖(即灰度圖) 37 imshow("diff", diff); 38 //在差異圖diff中查找輪廓,然后在原圖中繪制輪廓 39 vector<vector<Point>>contours2; 40 findContours(diff, contours2, CV_RETR_EXTERNAL, CV_CHAIN_APPROX_SIMPLE); 41 drawContours(img, contours2, 0, Scalar(0,255,0),-1);//-1表示繪制輪廓內部,正數表示輪廓線條粗細 42 imshow("result", img); 43 } 44 waitKey(0); 45 destroyAllWindows(); 46 }
輪廓的相關知識,后面會學到。
三、效果圖
二值圖如下
原圖備份后反二值化閾值圖copy,如下
copy的輪廓畫在全黑圖像上,如下
膨脹腐蝕如下
膨脹腐蝕相減(diff)如下
diff輪廓繪制在原圖上,如下
其他效果圖
繪制輪廓時,若繼續選擇-1(即繪制輪廓內部),會出現異常情況
將-1更改為輪廓線條粗細程度,則可以正確走出迷宮