简体   繁体   中英

Getting a good interpolation/fit for 1d curve in 3d space — Python

I have a set of 3d coordinates (x,y,z) to which I would like to fit a space curve. Does anyone know of existing routines for this in Python?

From what I have found ( https://docs.scipy.org/doc/scipy/reference/interpolate.html ), there are existing modules for fitting a curve to a set of 2d coordinates, and others for fitting a surface to a set of 3d coordinates. I want the middle path - fitting a curve to a set of 3d coordinates.

EDIT --

I found an explicit answer to this on another post here, using interpolate.splprep() and interpolate.splenv() . Here are my data points:

    import numpy as np
    data = np.array([[21.735556483642707,  7.9999120559310359,  -0.7043281314370935],
                    [21.009401429607784,  8.0101161320825103,  -0.16388503829177037],
                    [20.199370045383134,  8.0361339131845497,  0.25664085801558179],
                    [19.318149385194054,  8.0540100864979447,  0.50434139043379278],
                    [18.405497793567243,  8.0621753888918484,  0.57169888018720161],
                    [17.952649703401562,  8.8413995204241491,  0.39316793526155014],
                    [17.539007529982641,  9.6245700151356104,  0.14326173861202204],
                    [17.100154581079089,  10.416295524018977,  0.011339000091976647],
                    [16.645143439968102,  11.208477191735446,  0.070252116425261066],
                    [16.198247656768263,  11.967005154933993,  0.31087815045809558],
                    [16.661378578010989,  12.717314230004659,  0.54140549139204996],
                    [17.126106263351478,  13.503461982612732,  0.57743407626794219],
                    [17.564249250974573, 14.28890107482801, 0.42307198199366186],
                    [17.968265052275274,  15.031985807202176, 0.10156997950061938]])

Here is my code:

    from scipy import interpolate
    from mpl_toolkits.mplot3d import Axes3D

    data = data.transpose()

    #now we get all the knots and info about the interpolated spline
    tck, u= interpolate.splprep(data, k=5)
    #here we generate the new interpolated dataset, 
    #increase the resolution by increasing the spacing, 500 in this example
    new = interpolate.splev(np.linspace(0,1,500), tck, der=0)

    #now lets plot it!
    fig = plt.figure()
    ax = Axes3D(fig)
    ax.plot(data[0], data[1], data[2], label='originalpoints', lw =2, c='Dodgerblue')
    ax.plot(new[0], new[1], new[2], label='fit', lw =2, c='red')
    ax.legend()
    plt.savefig('junk.png')
    plt.show()

This is the image:

数据和适合度。

You can see that the fit is not good, while I am already using the maximum allowed fitting order value ( k=5 ). Is this because the curve is not fully convex? Does anyone know how I can improve the fit?

Depends on what the points represent, but if it's just position data, you could use a kalman filter such as this one written in python . You could just query the kalman filter at any time to get the "expected point" at that time, so it would work just like a function of time.

If you do plan to use a kalman filter, just set the initial estimate to your first coordinate, and set your covariance to be a diagonal matrix of huge numbers, this will indicate that you are very uncertain about the position of your next point, which will quickly lock the filter onto your coordinates.

You'd want to stay away from spline fitting methods, because splines will always go through your data.

You can fit a curve to any dimensional data. The curve fitting / optimization algorithms (say, in scipy.optimize ) all treat the observations you want to model as a plain 1-d array, and do not care what the independent variables are. If you flatten your 3d data, each value will correspond to an (x, y, z) tuple. You can just pass that information along as "extra" data to you fitting routine to help you calculate the model curve that will be fitted to your data.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM