如何估计分段平滑拟合噪声面具?

2024-10-03 02:45:41 发布

您现在位置:Python中文网/ 问答频道 /正文

我有一个二进制掩码,它起源于一条分段平滑曲线。每个基础曲线段都是平滑的,但段之间的连接可能是平滑的,也可能不是平滑的。 遮罩是有噪声的,因此它可能在基础曲线周围包含几个像素。下图显示了此类输入的示例:
input mask
我想估计一个拟合的基础曲线,鉴于这个输入没有任何其他先验知识,这将能够提供光滑和非光滑连接。你知道吗

我在python中工作,所以我尝试了几种可用的方法,例如numpy的多项式拟合、scipy的样条曲线平滑和pyqt拟合的非参数回归,但未能获得所需的输出。下面是一个代码示例:

    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()

对于本例中显示的参数,这些拟合既不能捕捉左侧的非平滑连接,也不能很好地拟合右侧的“尾部”:
current results
预期的结果应该像下图中的红色曲线一样,我预期位置1处的曲线是不平滑的,位置2处的曲线是平滑的。 expected results

我很乐意得到一个合适算法的参考。如果还有python实现,那就更好了。你知道吗


Tags: fromimportasnppltmaskrandom基础