OpenCV | 二值影像分析的技巧都在這裡

  • 2020 年 2 月 21 日
  • 筆記

輪廓屬性

二值影像分析最常見的一個主要方式就是輪廓發現輪廓分析,其中輪廓發現的目的是為輪廓分析做準備,經過輪廓分析我們可以得到輪廓各種有用的屬性資訊、常見的如下:

  • 輪廓面積
  • 輪廓周長
  • 輪廓幾何矩
  • 輪廓的最小外接矩形
  • 輪廓的最大外接矩形
  • 輪廓的最小外接圓
  • 輪廓的最小外接三角形
  • 輪廓擬合(支援擬合直線、橢圓、圓)
  • 輪廓的凸包
  • 輪廓層次資訊提取
  • 多邊形逼近
  • 計算歐拉數

函數介紹

OpenCV中提供大量輪廓分析函數,通過這些函數我們可以方便快捷的得到輪廓的各種有用屬性資訊、高效完成各種二值影像分析需求,下面是我總結的一些常用的函數列表與說明。

OpenCV中輪廓發現函數如下:

void cv::findContours(  InputArray      image,  OutputArrayOfArrays contours,  OutputArray hierarchy,  int   mode,  int   method,  Point       offset = Point()  )  

參數解釋如下:

image: 輸入影像、八位單通道的,背景為黑色 contours: 得到的輪廓影像 hierarchy: 層次影像,根據需要提取輪廓層次資訊 mode: 決定提取到層次資訊內容,是多層還是單層 method: 每個輪廓的編碼資訊 offset: 表示輪廓偏移,默認為0

輪廓分析相關的常用函數

// 計算輪廓面積  double cv::contourArea(  InputArray contour,  bool oriented = false  )  // 計算輪廓周長  double cv::arcLength(  InputArray      curve,  bool        closed  )  // 計算幾何矩與中心距  Moments cv::moments(  InputArray      array,  bool        binaryImage = false  )  // 計算最小外接矩形  RotatedRect cv::minAreaRect(  InputArray      points  )  // 計算最大外接矩形  Rect cv::boundingRect(  InputArray      array  )  // 計算最小外接圓/擬合圓  void cv::minEnclosingCircle(  InputArray      points,  Point2f &        center,  float &    radius  )  // 計算最小外接三角形/擬合三角形  double cv::minEnclosingTriangle(  InputArray      points,  OutputArray   triangle  )  // 擬合直線  void cv::fitLine(  InputArray      points,  OutputArray   line,  int   distType,  double    param,  double    reps,  double    aeps  )  // 擬合橢圓  RotatedRect cv::fitEllipse(  InputArray      points  )  // 計算凸包  void cv::convexHull(  InputArray      points,  OutputArray   hull,  bool        clockwise = false,  bool        returnPoints = true  )  // 多邊形逼近-逼近真實形狀  void cv::approxPolyDP(  InputArray      curve,  OutputArray   approxCurve,  double    epsilon,  bool        closed  )

靈活使用上述輪廓屬性資訊,可以實現對二值影像的幾何形狀判別、測量、面積過濾、獲取每個對象的幾何屬性包括面積、周長、編碼點、形狀、層次/位置資訊、歐拉數、中心位置、傾斜角度。

綜合運用程式碼演示

2020年 以前我分享過一些綜合使用的例子,列表如下(都看過你就贏了):

二值影像分析案例精選

OpenCV二值影像案例分析精選 | 第二期

OpenCV輪廓層次分析實現歐拉數計算

OpenCV尋找複雜背景下物體的輪廓

如何識別出輪廓準確的長和寬

OpenCV中幾何形狀識別與測量

OpenCV中BLOB特徵提取與幾何形狀分類

OpenCV直線擬合檢測

OpenCV中實現曲線與圓擬合

這裡再分享一個硬幣計數的例子!

原圖如下:

程式碼如下:

// 載入影像  Mat img = imread("D:/CoinsB.png");  imshow("Original Image", img);    // 閾值化操作  Mat gray, binary;  cvtColor(img, gray, COLOR_BGR2GRAY);  float t = threshold(gray, binary, 0, 255, THRESH_BINARY|THRESH_OTSU);  imshow("binary", binary);  imwrite("D:/binary1.png", binary);    // 形態學操作  Mat se = getStructuringElement(MORPH_RECT, Size(3, 3));  morphologyEx(binary, binary, MORPH_OPEN, se, Point(-1, -1));    // 輪廓發現  vector<Vec4i> hireachy;  vector<vector<Point>> contours;  bitwise_not(binary, binary);  findContours(binary, contours, hireachy, RETR_EXTERNAL, CHAIN_APPROX_SIMPLE, Point());  Mat result = img.clone();  Point2f center;  float radius;    // 輪廓分析  for (size_t t = 0; t < contours.size(); t++) {      double area = contourArea(contours[t]);      if (area < 1000) {          continue;      }      RotatedRect rrt = fitEllipse(contours[t]);      radius = min(rrt.size.width, rrt.size.height)/2.0;      circle(result, rrt.center, radius, Scalar(0, 0, 255), 4, 8, 0);      Moments mm = moments(contours[t]);      double cx = mm.m10 / mm.m00;      double cy = mm.m01 / mm.m00;      circle(result, Point(cx, cy), 2, Scalar(255, 0, 0), 2, 8, 0);  }    // 顯示結果  imshow("result", result);  imwrite("D:/drawing.png", result);  waitKey(0);

最終效果如下:

2020年少寫廢話,覺得不是廢話就點贊,做好自己該做的事情就是對自己最好的交待!