Bézier curve fitting with SciPy

后端 未结 7 614
醉酒成梦
醉酒成梦 2020-12-04 19:57

I have a set of points which approximate a 2D curve. I would like to use Python with numpy and scipy to find a cubic Bézier path which approximately fits the points, where I

7条回答
  •  挽巷
    挽巷 (楼主)
    2020-12-04 20:43

    I had the same problem as detailed in the question. I took the code provided Roland Puntaier and was able to make it work. Here:

    def get_bezier_parameters(X, Y, degree=2):
        """ Least square qbezier fit using penrose pseudoinverse.
    
        Parameters:
    
        X: array of x data.
        Y: array of y data. Y[0] is the y point for X[0].
        degree: degree of the Bézier curve. 2 for quadratic, 3 for cubic.
    
        Based on https://stackoverflow.com/questions/12643079/b%C3%A9zier-curve-fitting-with-scipy
        and probably on the 1998 thesis by Tim Andrew Pastva, "Bézier Curve Fitting".
        """
        if degree < 1:
            raise ValueError('degree must be 1 or greater.')
    
        if len(X) != len(Y):
            raise ValueError('X and Y must be of the same length.')
    
        if len(X) < degree + 1:
            raise ValueError(f'There must be at least {degree + 1} points to '
                             f'determine the parameters of a degree {degree} curve. '
                             f'Got only {len(X)} points.')
    
        def bpoly(n, t, k):
            """ Bernstein polynomial when a = 0 and b = 1. """
            return t ** k * (1 - t) ** (n - k) * comb(n, k)
    
        def bmatrix(T):
            """ Bernstein matrix for Bézier curves. """
            return np.matrix([[bpoly(degree, t, k) for k in range(degree + 1)] for t in T])
    
        def least_square_fit(points, M):
            M_ = np.linalg.pinv(M)
            return M_ * points
    
        T = np.linspace(0, 1, len(X))
        M = bmatrix(T)
        points = np.array(list(zip(X, Y)))
        return least_square_fit(points, M).tolist()
    

    To fix the end points of the curve, ignore the first and last parameter returned by the function and use your own points.

提交回复
热议问题