1

I have an image of points which "visually" form a closed circle. However, the points are unequally distributed along this "contour", which results in the center of mass being skewed. I tried using findContours but that doesn't find a closed line.

Is there a simple solution?

Edit: The points are stored in vectors for x and corresponding y-coordinates, I plotted them using cv::circle.

Image: white + red = whole vectors (720 points), red = first half of vector (360 points)

enter image description here

Original image:

enter image description here

ChrisF
  • 59
  • 8
  • sounds more like a `smallest enclosing ball` problem – BeyelerStudios Aug 17 '15 at 11:18
  • probably `convexHull` and `minEnclosingCircle` will help here. Post an image and some relevant code. – Miki Aug 17 '15 at 11:22
  • Add the original image too (no red dots), so I can provide a working example. – Miki Aug 17 '15 at 11:40
  • feel free to try my answer of http://stackoverflow.com/questions/27095483/improving-circle-detection/27100805#27100805 which uses a simple RANSAC to find circles.If you instead want to use `minEnclosingCircle` be aware that it really will find the ENCLOSING circle, so if you irregular distributed points are really bad on a single side, you might get a bad result, too. – Micka Aug 17 '15 at 11:40
  • ok... I think I misunderstood your problem. You don't necessarily want to find the "circle" but instead the center of gravity? But you can't compute CoG mathematically because there are more "point samples per inch" in some part of your data? Maybe you can just count the points in some kind of macro-cells and remove single points from some cells until all macro-blocks have same point count? – Micka Aug 17 '15 at 11:51

1 Answers1

2

You can use minEnclosingCircle to find the smallest circle containing all your points.

You get the center as output value of the function:

void minEnclosingCircle(InputArray points, Point2f& center, float& radius)

UPDATE

I tried a few different things. I assumed that you know that your final shape would be a circle.

  • minEnclosingCircle
  • boundingRect
  • fitEllipse

The best result (in this image) seems to be with fitEllipse.

Results

minEnclosingCircle:

enter image description here

boundingRect:

enter image description here

fitEllipse:

enter image description here

Code:

#include <opencv2\opencv.hpp>
#include <vector>

using namespace std;
using namespace cv;

int main()
{
    Mat1b img = imread("path_to_image", IMREAD_GRAYSCALE);

    vector<Point> points;
    findNonZero(img, points);

    Mat3b res;
    cvtColor(img, res, CV_GRAY2BGR);

    //////////////////////////////////
    // Method 1: minEnclosingCircle
    //////////////////////////////////

    /*Point2f center;
    float radius;
    minEnclosingCircle(points, center, radius);

    circle(res, center, radius, Scalar(255,0,0), 1);
    circle(res, center, 5, Scalar(0,255,0), 1);*/


    //////////////////////////////////
    // Method 2: boundingRect
    //////////////////////////////////

    /*Rect bbox = boundingRect(points);

    rectangle(res, bbox, Scalar(0,255,255));
    circle(res, Point(bbox.x + bbox.width/2, bbox.y + bbox.height/2), 5, Scalar(0,0,255));*/


    //////////////////////////////////
    // Method 3: fit ellipse
    //////////////////////////////////

    RotatedRect ell = fitEllipse(points);
    ellipse(res, ell, Scalar(255,255,0));
    circle(res, ell.center, 5, Scalar(255,0,255));

    return 0;
}
Miki
  • 40,887
  • 13
  • 123
  • 202