1. 程式人生 > >25、【opencv入門】輪廓查找與繪制(3)——凸包

25、【opencv入門】輪廓查找與繪制(3)——凸包

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)——凸包