2

I'm using the cv::HoughCircles() function from OpenCV to detect circles in an image. The function takes an output parameter of type cv::OutputArray to provide the results. Based on the example code I am using a std::vector<cv::Vec4f> as output parameter, so the code looks something like this:

std::vector<cv::Vec4f> found_circles;
cv::HoughCircles(gray_image, found_circles, cv::HOUGH_GRADIENT, 1, 1, 100, 100, 10, 20);

Each element in found_circles is now a cv::Vec4f containing x/y/radius/vote values. This basically works fine; but the code for accessing the details of the detected circles is not easily readable, because I have to access the members by index rather than by name.
For example, to sort the circles by radius:

std::sort(found_circles.begin(), found_circles.end(), [](const cv::Vec4f &c1, const cv::Vec4f &c2) -> bool {
  return c1[2] > c2[2];
});

It is not easy to see that c1[2] is the radius value.

Is there a way to access the circle details by name, so that the above code looks rather like this:

std::sort(found_circles.begin(), found_circles.end(), [](const cv::Vec4f &c1, const cv::Vec4f &c2) -> bool {
  return c1.radius > c2.radius;
});

For example, is there a way to access the cv::Vec4f elements with some aliased name? Or can I (with reasonable amount of code) create a custom data structure to pass as result parameter to cv::HoughCircles(), instead of std::vector<cv::Vec4f>?

I'm using OpenCV 4.5.3 and C++17.

oliver
  • 6,204
  • 9
  • 46
  • 50
  • 3
    `inline double radius(cv::Vec4f const& v) { return v[2]; }` or `enum CvHelper : std::size_t { radius = 2 };` and then `return c1[radius] > c2[radius];` – Eljay Jun 15 '22 at 16:00
  • 2
    You could define an `enum { X, Y, Radius, Vote };` to access the elements more conveniently. – Scheff's Cat Jun 15 '22 at 16:01
  • @Scheff'sCat: thanks, I went with your suggestion in the end. It's easy and looks quite OK. – oliver Jun 20 '22 at 14:02

1 Answers1

1

You cannot force a type to use names that the type doesn't use. You can create a type that wraps cv::Vec4 which uses member functions to call the particular indices. You can even create non-member functions in the cv namespace whose names match what you want.

But a type has only the meaning that the creator of that type gave it. If you want specialized nomenclature, you'll need a specialized type.

Nicol Bolas
  • 449,505
  • 63
  • 781
  • 982