25、【opencv入門】輪廓查找與繪制(3)——凸包
阿新 • • 發佈:2018-09-18
ise 技術分享 bool and s函數 span spa push_back 返回
一簡介
1、凸包
凸包(Convex Hull)是一個計算機幾何圖形學中的概念, 簡單來說, 給定二維平面點集, 凸包就是能夠將最外層的點連接起來構成的凸多邊形, 它能夠包含點集中所有的點。物體的凸包檢測場應用在物體識別、手勢識別及邊界檢測等領域。
A-H是被標出的凸包缺陷
2、尋找凸包---convexHull()
1 CV_EXPORTS_W void convexHull(InputArray points, OutputArray hull, bool clockwise=false, bool returnPoints = true);
points: 輸入的二維點集, 可以填Mat類型或std::vector
hull: 函數調用後找到的凸包
clockwise: 操作方向標誌符, 當為true時, 輸出的凸包為順時針方向, false為逆時針方向(假定坐標系x軸指向右,y軸指向上方)
returnPoints: 操作標誌符, 默認值true. 當標誌符為true時, 函數返回凸包各個點, 否則返回凸包各點的指數, 當輸出數組是std::vector時, 此標誌被忽略
示例:
1 vector<int> hull; 2 convexHull(Mat(points), hull, true);
1 vector<vector<Point>> hull(contours.size());2 for(int i = 0; i < contours.size(); i++) 3 { 4 convexHull(Mat(contours[i]), hull[i], true); 5 }
3、凸包缺陷分析---convexityDefects()
1 CV_EXPORTS_W void convexityDefects(InputArray contour, InputArray convexhull, OutputArray convexityDefects);
contour: 表示輸入參數檢測到的輪廓, 可以用findContours函數獲得
convexhull: 輸入參數表示檢測到的凸包, 可以用convexHull函數獲得
convexityDefects: 檢測到的最終結果, 應為vector<vector<Vec4i>>類型, Vec4i存儲了起始點、結束點、距離及最遠點到凸包的距離
二、繪制點集的凸包
1 //繪制點集的凸包 2 #include<opencv2/opencv.hpp> 3 4 using namespace cv; 5 6 int main() 7 { 8 //---繪制點集的凸包 9 Mat img(400, 400, CV_8UC3, Scalar::all(0)); //定義繪制圖像 10 RNG rng; //定義隨機數對象 11 while(1) 12 { 13 char key; 14 int count = (unsigned int)rng % 100; //定義點的個數 15 vector<Point> points; //定義點集 16 for(int i=0; i<count; i++) 17 { 18 Point pt; 19 pt.x = rng.uniform(img.cols/4, img.cols*3/4); //設定點的x範圍 20 pt.y = rng.uniform(img.rows/4, img.rows*3/4); //設定點的y範圍 21 points.push_back(pt); 22 } 23 24 //檢測凸包 25 vector<int> hull; 26 convexHull(Mat(points), hull, true); 27 28 img = Scalar::all(0); 29 for(int i = 0; i < count; i++ ) 30 circle(img, points[i], 3, Scalar(rng.uniform(0, 255), rng.uniform(0, 255), rng.uniform(0, 255)), CV_FILLED, CV_AA); 31 32 //準備參數 33 int hullcount = (int)hull.size(); //凸包的邊數 34 Point point0 = points[hull[hullcount-1]]; //連接凸包邊的坐標點 35 36 //繪制凸包的邊 37 for(int i = 0; i < hullcount; i++ ) 38 { 39 Point point = points[hull[i]]; 40 circle(img, point, 8, Scalar(0, 255, 0), 2, 8); 41 line(img, point0, point, Scalar(255, 255, 255), 2, CV_AA); 42 point0 = point; 43 } 44 45 //顯示效果圖 46 imshow("img", img); 47 48 //按下ESC,Q,或者q,程序退出 49 key = (char)waitKey(); 50 if( key == 27 || key == ‘q‘ || key == ‘Q‘ ) 51 break; 52 } 53 return 0; 54 }
三、繪制輪廓的凸包
1 //繪制輪廓的凸包 2 #include<opencv2/opencv.hpp> 3 4 using namespace cv; 5 6 int main() 7 { 8 Mat srcImg = imread("E://12.jpg"); 9 imshow("src", srcImg); 10 Mat dstImg2 = srcImg.clone(); 11 Mat tempImg(srcImg.rows, srcImg.cols, CV_8UC3, Scalar::all(0)); //用於繪制凸包 12 Mat dstImg(srcImg.rows, srcImg.cols, CV_8UC3, Scalar::all(0)); //用於繪制輪廓 13 cvtColor(srcImg, srcImg, CV_BGR2GRAY); 14 threshold(srcImg, srcImg, 100, 255, CV_THRESH_BINARY); //二值化 15 16 vector<vector<Point>> contours; 17 vector<Vec4i> hierarcy; 18 findContours(srcImg, contours, hierarcy, CV_RETR_EXTERNAL, CV_CHAIN_APPROX_NONE); 19 vector<vector<Point>> hull(contours.size()); 20 for(int i=0; i<contours.size(); i++) 21 { 22 convexHull(Mat(contours[i]), hull[i], true); //查找凸包 23 drawContours(dstImg, contours, i, Scalar(255, 255, 255), -1, 8); //繪制輪廓 24 //drawContours(dstImg, hull, i, Scalar(rand()%255, rand()%255, rand()%255), 2, 8); 25 drawContours(tempImg, hull, i, Scalar(255, 255, 255), -1, 8); 26 } 27 imshow("hull", tempImg); 28 imshow("contours", dstImg); 29 30 Mat diffImg; 31 absdiff(tempImg, dstImg, diffImg); //圖像相減 32 Mat element = getStructuringElement(MORPH_RECT, Size(3, 3), Point(-1, -1)); 33 erode(diffImg, diffImg, element); 34 imshow("diff", diffImg); 35 36 vector<vector<Point>> contours2; 37 vector<Vec4i> hierarcy2; 38 cvtColor(diffImg, diffImg, CV_BGR2GRAY); //轉為灰度圖 39 threshold(diffImg, diffImg, 100, 255, CV_THRESH_BINARY); //二值化 40 findContours(diffImg, contours2, hierarcy2, CV_RETR_EXTERNAL, CV_CHAIN_APPROX_NONE); 41 drawContours(dstImg2, contours2, -1, Scalar(0, 0, 255), 2, 8); //紅色繪制缺陷輪廓 42 imshow("defects", dstImg2); 43 waitKey(0); 44 return 0; 45 }
25、【opencv入門】輪廓查找與繪制(3)——凸包