1. 程式人生 > >凸包(Convex Hull)

凸包(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);
}