Fit Points With a Smooth Curve
<p>I want to fit a set of points on a image with a <strong>smooth</strong> curve in python. The curve may be open or closed. Moreover, I want to get the curve plotted over the image as a mask that has the same size as the image. Is there any modules or functions I can refer to? Thanks.</p>

<p>This is generally called Parametric Interpolation. There is a scipy function that does just that called <a href="http://scipy.github.io/devdocs/generated/scipy.interpolate.splprep.html" rel="nofollow">splprep</a>. The steps you are requesting are:</p>

<p><strong>1)</strong> Smooth a shape (built with ordered points, if not use <a href="http://docs.scipy.org/doc/scipy/reference/generated/scipy.spatial.ConvexHull.html" rel="nofollow">convex hull</a> first, check <a href="http://stackoverflow.com/questions/36763853/plotting-a-set-of-given-points-to-form-a-closed-curve-in-matplotlib/36764052#36764052">this question</a>).</p>

<p><strong>NOTE:</strong> <em>for more on how to create a shape over an image check</em> <a href="http://stackoverflow.com/questions/37103604/extract-image-segment-from-polygon-with-skimage/37149857#37149857">this question</a>.</p>

<p><strong>2)</strong> Use the smooth shape to build a mask over an image (lets say 2D array).</p>

<p>The following recipe does that:</p>

<pre><code>import numpy as np
from scipy.interpolate import splprep, splev
import matplotlib.pyplot as plt
from matplotlib import path

# Building a shape with scattered points.
x = np.array([10, 10, 0, 0, 10, 10, 20, 20, 30, 30, 20, 20, 10]) + 10
y = np.array([0, 10, 10, 20, 20, 30, 30, 20, 20, 10, 10, 0, 0]) + 10
image = np.random.randint(0, 10, (50, 50))

# Smoothing the shape.
# spline parameters
s = 3.0 # smoothness parameter
k = 2 # spline order
nest = -1 # estimate of number of knots needed (-1 = maximal)
t, u = splprep([x, y], s=s, k=k, nest=-1)
xn, yn = splev(np.linspace(0, 1, 500), t)

# Showing the original shape
plt.imshow(image.T, origin='lower', interpolation='nearest', cmap='gray')
plt.plot(x, y, color='b', linewidth=3)
plt.xlim(0, 50)
plt.ylim(0, 50)
plt.show()

# Showing the original shape vs smooth shape
plt.imshow(image.T, origin='lower', interpolation='nearest', cmap='gray')
plt.plot(x, y, color='b', linewidth=3)
plt.plot(xn, yn, color='r', linewidth=3)
plt.xlim(0, 50)
plt.ylim(0, 50)
plt.show()

# Changing values inside the shape (and outside). Building a boolean mask.
image1 = image.copy()
image2 = image.copy()
mask = np.zeros(image.shape)
xx, yy = np.meshgrid(range(image.shape[0]),range(image.shape[1]))
shapes = np.hstack((xn[:, np.newaxis], yn[:, np.newaxis]))
p = path.Path(shapes)
for i in range(image.shape[0]):
    for j in range(image.shape[1]):
        if not p.contains_point((i, j)):
            image1[i, j] = 0
            mask[i, j] = True
        else:
            image2[i, j] = 0

# Showing changes in image for values outside shape.
plt.imshow(image1.T, origin='lower', interpolation='nearest', cmap='gray')
plt.plot(xn, yn, color='r', linewidth=3)
plt.xlim(0, 50)
plt.ylim(0, 50)
plt.show()

# Showing changes in image for values inside shape.
plt.imshow(image2.T, origin='lower', interpolation='nearest', cmap='gray')
plt.plot(xn, yn, color='r', linewidth=3)
plt.xlim(0, 50)
plt.ylim(0, 50)
plt.show()
</code></pre>

<p>The code is commented for you to know what is happening at each of the plots of the results:</p>

<p><a href="http://i.stack.imgur.com/FmrIe.png" rel="nofollow"><img src="http://i.stack.imgur.com/FmrIe.png" alt="Simple Shape over image"></a>
1. <em>Simple Shape over image</em></p>

<p><a href="http://i.stack.imgur.com/c3QX6.png" rel="nofollow"><img src="http://i.stack.imgur.com/c3QX6.png" alt="Simple vs Smooth shape over image"></a>
2. <em>Simple vs Smooth shape over image</em></p>

<p><a href="http://i.stack.imgur.com/Q6REa.png" rel="nofollow"><img src="http://i.stack.imgur.com/Q6REa.png" alt="Use values inside shape"></a>
3. <em>Use values inside shape</em></p>

<p><a href="http://i.stack.imgur.com/ZLu8a.png" rel="nofollow"><img src="http://i.stack.imgur.com/ZLu8a.png" alt="Use values outside shape"></a>
4. <em>Use values outside shape</em></p>

python opencv matplotlib computer-vision skimage