什么是明智的解决方案在很大程度上取决于您试图用插值像素回答什么问题——请注意:对丢失的数据进行外推可能会导致非常误导的答案!
径向基函数插值/核平滑
就 Python 中可用的实际解决方案而言,填充这些像素的一种方法是使用 Scipy 的径向基函数插值实现(参见此处),该实现旨在用于分散数据的平滑/插值。
给定您的矩阵M
和底层一维坐标数组r
和c
(这样M.shape == (r.size, c.size)
),其中 M 的缺失条目设置为nan
,这似乎与线性 RBF 内核一起工作得很好,如下所示:
import numpy as np
import scipy.interpolate as interpolate
with open('measurement.txt') as fh:
M = np.vstack(map(float, r.split(' ')) for r in fh.read().splitlines())
r = np.linspace(0, 1, M.shape[0])
c = np.linspace(0, 1, M.shape[1])
rr, cc = np.meshgrid(r, c)
vals = ~np.isnan(M)
f = interpolate.Rbf(rr[vals], cc[vals], M[vals], function='linear')
interpolated = f(rr, cc)
这会产生您上面链接到的数据的以下插值,虽然看起来合理,但确实突出了缺失样本与真实数据的比率是多么不利:
高斯过程回归/克里金法
克里金插值可通过 scikit-learn 库中的高斯过程回归实现(它本身基于 Matlab 的 DACE 克里金工具箱)获得。这可以按如下方式调用:
from sklearn.gaussian_process import GaussianProcess
gp = GaussianProcess(theta0=0.1, thetaL=.001, thetaU=1., nugget=0.01)
gp.fit(X=np.column_stack([rr[vals],cc[vals]]), y=M[vals])
rr_cc_as_cols = np.column_stack([rr.flatten(), cc.flatten()])
interpolated = gp.predict(rr_cc_as_cols).reshape(M.shape)
这产生了与上面的径向基函数示例非常相似的插值。在这两种情况下,都有很多参数需要探索——这些参数的选择很大程度上取决于您可以对数据做出的假设。(上面 RBF 示例中使用的线性内核的一个优点是它没有自由参数)
修补
最后,一个完全以视觉为动机的解决方案是使用 OpenCV 的修复功能,尽管这假设 8 位数组 (0 - 255),并且没有直接的数学解释。