opencv之hugh提取圆孔

背景:需要在image中提取圆孔圆心的位置,用到opencv中的hugh检测的方法,提取的效果还不错。但是只是初步的版本,没有增加更多的鲁棒性判断。

#include <opencv2/imgcodecs.hpp>
#include <opencv2/imgproc/imgproc.hpp>
#include <opencv2/highgui/highgui.hpp>

#include <iostream>

int main(int argc, char** argv)
{
  // read a image 
  std::string file_name = "/home/liuzhiyang/image.png";
  cv::Mat input_image = cv::imread(file_name, cv::IMREAD_COLOR);
  if (input_image.empty())
  {
    std::cout << "Error to open image file !" << std::endl;
    return 0;
  }

  // cv::imshow("origin image", input_image);

  // undistort image
  cv::Mat undistort_image;
  float fx = 1.0757955405501191e+03, fy = 1.0762345733674481e+03;
  float cx = 9.6249394948422218e+02, cy = 6.1957628038839391e+02;
  float k1 = -1.1995613777994101e-01, k2 = 8.6245969435724004e-02, k3 = -2.6778267188218002e-02;
  float p1 = 1.0621717082800000e-03, p2 = 5.4033385896265832e-04;
  cv::Mat camera_matrix = (cv::Mat_<float>(3, 3) << fx, 0.0, cx, 0.0, fy, cy, 0.0, 0.0, 1.0);
  cv::Mat distortion_coeff = (cv::Mat_<float>(1, 5) << k1, k2, p1, p2, k3);

  // cv::undistort(input_image, undistort_image, camera_matrix, distortion_coeff);
  // cv::imshow("undistortion image", undistort_image);

  // // extract roi area
  // cv::Mat roi_image = input_image(cv::Rect(0, 0, input_image.cols / 2, input_image.rows / 2));
  // cv::imshow("roi image", roi_image);

  //extract hough circles
  cv::Mat gray_image;
  cv::cvtColor(input_image, gray_image, cv::COLOR_BGR2GRAY);
  cv::GaussianBlur(gray_image, gray_image, cv::Size(9, 9), 1, 1);
  std::vector<cv::Vec3f> circles_pixel(4);
  int min_radius = gray_image.rows / 16;
  int max_radis = gray_image.rows / 8;
  int min_distance = gray_image.rows / 8;
  cv::HoughCircles(gray_image, circles_pixel, cv::HOUGH_GRADIENT, 1, min_distance, 200, 100, min_radius, max_radis); 

  // get normalization plane coordination
  std::vector<cv::Vec3f> circles_coor(4);
  for (size_t i = 0; i < circles_pixel.size(); ++i)
  {
    circles_coor[i][0] = (circles_pixel[i][0] - cx) / fx;
    circles_coor[i][1] = (circles_pixel[i][1] - cy) / fy;
    std::cout << circles_coor[i][0] << "  " << circles_coor[i][1] << std::endl;
  } 

  // show circles
  for( size_t i = 0; i < circles.size(); i++ )
  {
    cv::Vec3i c = circles[i];
    cv::circle( gray_image, cv::Point(c[0], c[1]), c[2], cv::Scalar(0,0,255), 1, cv::LINE_AA);
    cv::circle( gray_image, cv::Point(c[0], c[1]), 2, cv::Scalar(0,255,0), 1, cv::LINE_AA);
  }
  cv::imshow("detected circles", gray_image);
  cv::waitKey(0);
}
  • 后记

    在使用cv::HoughCircles()函数前,高斯模糊的参数、圆孔半径和最小距离设置对提取圆孔的准确性影响还是挺大的。