Evaluating/Fitting an ellipse from scattered points

前端 未结 5 1592
野性不改
野性不改 2021-01-17 05:04

Here is the deal. I have multiple points (X,Y) that form an \'ellipse like\' shape.

I would like to evaluate/fit the \'best\' ellipse possible and get its properties

5条回答
  •  醉梦人生
    2021-01-17 05:47

    I will explain how I would approach the problem. I would suggest a hill climbing approach. First compute the gravity center of the points as a start point and choose two values for a and b in some way(probably arbitrary positive values will do). You need to have a fit function and I would suggest it to return the number of points (close enough to)lying on a given ellipse:

    int fit(x, y, a, b)
      int res := 0
      for point in points
        if point_almost_on_ellipse(x, y, a, b, point)
          res = res + 1
        end_if
      end_for
      return res
    

    Now start with some step. I would choose a big enough value to be sure the best center of the elipse will never be more then step away from the first point. Choosing such a big value is not necessary, but the slowest part of the algorithm is the time it takes to get close to the best center so bigger value is better, I think.

    So now we have some initial point(x, y), some initial values of a and b and an initial step. The algorithm iteratively chooses the best of the neighbours of the current point if there is any neighbour better then it, or decrease step twice otherwise. Here by 'best' I mean using the fit function. And also a position is defined by four values (x, y, a, b) and it's neighbours are 8: (x+-step, y, a, b),(x, y+-step, a, b), (x, y, a+-step, b), (x, y, a, b+-step)(if results are not good enough you can add more neighbours by also going by diagonal - for instance (x+-step, y+-step, a, b) and so on). Here is how you do that

    neighbours = [[-1, 0, 0, 0], [1, 0, 0, 0], [0, -1, 0, 0], [0, 1, 0, 0],
                  [0, 0, -1, 0], [0, 0, 1, 0], [0, 0, 0, -1], [0, 0, 0, 1]]
    iterate (cx, cy, ca, cb, step) 
      current_fit = fit(cx, cy, ca, cb)
      best_neighbour = []
      best_fit = current_fit
      for neighbour in neighbours
        tx = cx + neighbour[0]*step
        ty = cx + neighbour[1]*step
        ta = ca + neighbour[2]*step
        tb = cb + neighbour[3]*step
        tfit = fit(tx, ty, ta, tb)
        if (tfit > best_fit) 
          best_fit = tfit
          best_neighbour = [tx,ty,ta,tb]
        endif
      end_for
      if best_neighbour.size == 4
        cx := best_neighbour[0]
        cy := best_neighbour[1]
        ca := best_neighbour[2]
        cb := best_neighbour[3]
      else 
        step = step * 0.5
      end_if
    

    And you continue iterating until the value of step is smaller then a given threshold(for instance 1e-6). I have written everything in pseudo code as I am not sure which language do you want to use.

    It is not guaranteed that the answer found this way will be optimal but I am pretty sure it will be good enough approximation.

    Here is an article about hill climbing.

提交回复
热议问题