Search code examples
pythonnumpymatplotlibgeometrybspline

How to smooth out a stroke, given some coordinates (x, y) of the stroke in order?


I am currently working on a project where I need to create an image of a stroke smoothed out given some ordered coordinates of the stroke. Suppose I have some points

import numpy as np
X = np.array([1, 3, 6, 8, 5])
Y = np.array([1, 8, 4, 4, 1])
plt.plot(X, Y)

figure-1

But what I want is making a smoothed out points collection which will plot this (This is just a hand drawn picture, I think you got the point):

hand drawing

I have seen this question which works for only functions (one x will only output one y). But I need a spline for a relation (not a function). Thank you in advance.


Solution

  • You can use B-spline (splprep and splev) from scipy.interpolate:

    import numpy as np
    from scipy.interpolate import splprep, splev
    import matplotlib.pyplot as plt
    
    X = np.array([1, 3, 6, 8, 5])
    Y = np.array([1, 8, 4, 4, 1])
    pts = np.vstack((X, Y))
    # Find the B-spline representation of an N-dimensional curve
    tck, u = splprep(pts, s=0.0)
    u_new = np.linspace(u.min(), u.max(), 1000)
    # Evaluate a B-spline
    x_new, y_new = splev(u_new, tck)
    
    plt.plot(x_new, y_new, 'b--')
    plt.show()
    

    That will give you something similar for what you asked:

    enter image description here

    You can play with the splprep parameters to change the result. You can find more details in this StackOverflow post.