凸包(Convex Hull)
給定二維平面上的點集,凸包就是將最外層的點連線起來構成的凸多邊形
凸缺陷(convexity defects)是凸包比物體輪廓多的部分
函式:convexHull尋找凸包函式
程式:隨機生成一些座標點,然後對這些點構成的幾何圖形求凸包
int main()
{
Mat src;
src.create(600,600,CV_8UC3);//生成一張畫布
RNG rng;
vector<Point2i> points;
for(int i=0;i<200;i++) //生成200個隨機點
{
Point point;
point.x=rng.uniform(src.cols*0.2,src.cols*0.6); //只有單獨的point格式可以用point.x,而vector<point>格式不可以
point.y=rng.uniform(src.rows*0.4,src.rows*0.8);
points.push_back(point);
circle(src,point,3,Scalar(255,0,0),CV_FILLED,9,0); //順便畫出這些點,準備用線進行連線,視覺化
}//隨機點生成完畢
//核心函式,尋找凸包
vector<int> hull;
convexHull(points,hull);//第三個引數是遍歷方向,第四個引數如果輸出是vector型資料,看你定義的是vector的哪個型別,point輸出點或者int輸出指數
int hullCount=hull.size();//線段的條數
Point point0=points[hull[hullCount-1]];//point0初始化,比如一共60條線段60個點,這就是第59個點,方便迴圈開始和第0個點連線
for(int j=0;j<hullCount;j++)
{
Point point1=points[hull[j]]; //這地方要注意的是hull[j]對應的點要去points裡面尋找才行
line(src,point1,point0,Scalar(255,255,255),1,8,0);
point0=point1;
}
imshow("a",src);
waitKey(0);
}
程式二:利用滑動條,求已讀圖片的凸包
int main()
{
src=imread("kele.jpg",0);
threshold(src,con_output,100,255,THRESH_BINARY);
findContours(con_output,contourPoint,hierarchy,RETR_CCOMP,CHAIN_APPROX_SIMPLE);
//上面的語句找到輪廓,並以vector<vector<Point>>的形式儲存
//下面應該先來一層迴圈,遍歷所有的輪廓,把每一個輪廓當成一個影象去找凸點
dst.create(con_output.size(),CV_8UC3);
vector<vector<Point>>hull(contourPoint.size());//這裡得到的是第i張輪廓圖樣本點外圍的集合,後面是初始化它的尺寸!!!初始化少了會出錯!!!
//而且在這裡證明了hull可以用vector<int>或者vector<Point>
vector<Point> points;
vector<Point> contour_hull;
for(int i=0;i<contourPoint.size();i++) //這裡有待探究的是.size()到底是輪廓數還是點數
{
convexHull(Mat(contourPoint[i]),hull[i]); //用凸點函式進行計算Mat加不加都行,
//對於OutputArray hull引數可以為std::vector<int>,這是返回的是凸包點在原輪廓點集中的索引,當為std::vector<cv::Point>時,表示的是凸包點的位置
}
for(int j=0;j<contourPoint.size();j++)
{
drawContours(dst,contourPoint,j,Scalar(0,0,255),1,8);
drawContours(dst,hull,j,Scalar(255,0,0),1,8);
}
imshow("a",dst);
waitKey(0);
}