I have a binary mask that originated from a piece-wise smooth curve. Each underlying curve segment is smooth, but connections between segments may or may not be smooth.
The mask is noisy so it might contain several pixels around the underlying curve. Image below shows an example of such input:
I want to estimate a fit to the underlying curve, given this input without any other prior knowledge, that will be able to provide both smooth and non-smooth connections.
I'm working in python so I tried several methods available there, such as numpy's polynomial fit, scipy's spline smoothing and pyqt-fit's non-parameteric regression, but was not able to get to the desired output. Here's a code example:
from imageio import imread
import random
import numpy as np
from scipy.interpolate import UnivariateSpline
import pyqt_fit.nonparam_regression as smooth
from pyqt_fit import npr_methods
from matplotlib import pyplot as plt
mask = imread(r'C:\mask.bmp')
ys, xs = np.where(mask)
# add tiny noise and sort - silly way to comply to UnivariateSpline's requirement of "x must be strictly increasing"
xs = np.array([x + random.random() * 1e-4 for x in xs])
sorter = np.argsort(xs)
xs = xs[sorter]
ys = ys[sorter]
# polynomial fit
p = np.poly1d(np.polyfit(xs, ys, 5))
# spline smoothing
spl = UnivariateSpline(xs, ys, k=3, s=1e9)
# non-parameteric regression
k = smooth.NonParamRegression(xs, ys, method=npr_methods.LocalPolynomialKernel(q=3))
k.fit()
plt.figure()
plt.imshow(mask, cmap='gray')
linexs = np.array(range(mask.shape[1]))
plt.plot(linexs, k(linexs), 'y', lw=1)
plt.plot(linexs, spl(linexs), 'g', lw=1)
plt.plot(linexs, p(linexs), 'b', lw=1)
plt.show()
For the parameters shown in this example, these fits both fail to capture the non-smooth connection on the left, as well as to provide a good fit for the "tail" on the right:
Expected results should behave like the red curve in the image below, where I expect the curve at location 1 to be non-smooth and at location 2 to be smooth.
I'd be happy to get a reference to a suitable algorithm. If there's also a python implementation, that would be a plus.