提取輪廓和描述子

來源:互聯網
上載者:User
Mat image = imread("D:/picture/images/binaryGroup.bmp",0);  if(!image.data)      return -1;  imshow("源映像",image);    //擷取輪廓  std::vector<std::vector<Point>> contours;  //擷取輪廓:  findContours(image,         //映像      contours,               //輪廓點                      //包含映像拓撲結構的資訊(選擇性參數,這裡沒有選)      CV_RETR_EXTERNAL,           //擷取輪廓的方法(這裡擷取外圍輪廓)      CV_CHAIN_APPROX_NONE);      //輪廓近似的方法(這裡不近似,擷取全部輪廓)  //列印輪廓資訊  std::cout<<"共有外圍輪廓:"<<contours.size()<<"條"<<std::endl;  std::vector<std::vector<Point>>::const_iterator itContours = contours.begin();  for(;itContours != contours.end();++itContours)  {      std::cout<<"每個輪廓的長度: "<<itContours->size()<<std::endl;  }  

注意到輪廓的儲存格式為std::vector<std::vector<Point>>,他說明整個輪廓是若干條輪廓按一定順序組成的,而每個輪廓中的點也是有順序的。

畫出輪廓就比較簡單了:

//畫出輪廓  Mat result(image.size(),CV_8U,Scalar(255));  //畫出輪廓,參數為:畫板,輪廓,輪廓指示(這裡畫出所有輪廓),顏色,線粗  drawContours(result,contours,-1,Scalar(0),2);  imshow("提取外圍輪廓",result);  

還要注意提取輪廓的方法還有很多種,比如CV_RETR_LIST代表所有輪廓

findContours(image,         //映像      contours,               //輪廓點                      //包含映像拓撲結構的資訊(選擇性參數,這裡沒有選)      CV_RETR_LIST,           //擷取輪廓的方法(這裡擷取所有輪廓)      CV_CHAIN_APPROX_NONE);      //輪廓近似的方法(這裡不近似,擷取全部輪廓  //畫出輪廓  drawContours(result,contours,-1,Scalar(0),2);  imshow("提取所有輪廓",result);  

通常,這樣提取的輪廓包含一些我們不希望的輪廓(比如一些小洞),或者假如我們知道我們感興趣的物體輪廓的大概範圍時,我們就可以用下面的辦法縮小目標範圍:

//除去太長或者太短的輪廓int cmin = 100;int cmax = 1000;std::vector<std::vector<Point>>::const_iterator itc = contours.begin();while(itc != contours.end()){if(itc->size() < cmin || itc->size() > cmax)itc = contours.erase(itc);else++itc;}//把結果畫在源映像上:Mat original = imread("D:/picture/images/group.jpg");if(!original.data)return -1;drawContours(original,contours,-1,Scalar(255,255,255),2);imshow("動物的輪廓",original);//將輪廓重繪於白板上result.setTo(Scalar(255));drawContours(result,contours,-1,Scalar(0),1);

怎麼提取輪廓的特徵呢?OpenCV提供了很多函數,我們展示其中的幾個:

//輪廓的形狀描述子  //外接矩形  Rect r0 = boundingRect(Mat(contours[0]));  rectangle(result,r0,Scalar(0),2);    //最小外接圓  float radius;  Point2f center;  minEnclosingCircle(Mat(contours[1]),center,radius);  circle(result,Point(center),static_cast<int>(radius),Scalar(0),2);    //多邊形估計  std::vector<Point> poly;  //參數為:輸入映像的2維點集,輸出結果,估計精度,是否閉合  approxPolyDP(Mat(contours[2]),poly,5,true);  std::cout<<"多邊形大小:"<<poly.size()<<std::endl;  //畫出結果  std::vector<Point>::const_iterator itp = poly.begin();  while(itp != poly.end()-1)  {      line(result,*itp,*(itp+1),Scalar(0),2);      ++itp;  }  //將第一個點和最後一點連起來  line(result,*(poly.begin()),*(poly.end()-1),Scalar(128),2);      //計算凸包  std::vector<Point> hull;  convexHull(Mat(contours[3]),hull);  std::vector<cv::Point>::const_iterator it= hull.begin();  while(it != (hull.end()-1))  {      line(result,*it,*(it+1),Scalar(0),2);      ++it;  }  line(result,*(hull.begin()),*(hull.end()-1),Scalar(0),2);      //計算矩資訊  itc = contours.begin();  while(itc != contours.end())  {      //計算所有的距      Moments mom = moments(Mat(*itc++));      //計算並畫出質心      circle(result,Point(mom.m10/mom.m00,mom.m01/mom.m00),2,Scalar(2),2);  }  imshow("形狀描述子",result);  

我們再次看到,輪廓的確是有順序的。值得注意的是矩資訊:OpenCV提供了一個結構體Moments,它的元素就是計算好的矩資訊,裡面存放了常用的距。

其實,OpenCV還提供了許多其他的形狀描述子,比如函數cv::minAreaRect計算了最小外界傾斜的矩形。函數cv::contourArea估計輪廓地區的面積(裡面的像素數)。函數cv::pointPolygonTest計算一個點是否在輪廓內,cv::matchShapes測量了2兩個輪廓的相似程度等等。

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.