在图像处理和数字地形建模等领域,插值技术被广泛应用。本文将比较不同的插值策略。插值的目的是通过创建中间点来“密集化”稀疏数据集。以一个4x5的矩阵为例,为每个值分配一个任意颜色。将原始数据集中的每个间隔分成N=100个点,创建一个300x400像素的图像。
以下是初始矩阵:
方法1 - 最近邻插值 最简单的插值策略就是取最近数据点的值。它也可以被称为“零度插值”,由函数nni(x,y)=Vround(x),round(y)描述。输出矩阵简单地由M[i,j]=nni(i/N, j/N)生成。
方法2 -双线性插值 这是最受欢迎的方法之一。插值函数在X和Y上都是线性的(因此得名——双线性):
方法3 - 双二次插值 如果一度(线性)函数让得到了一个连续的插值函数,但导数不连续,那么使用二度(称为二次或抛物线)函数可能会给一个更好的插值函数。
方法4 - 双三次插值 如果想要斜率连续性,必须使用更高一度的函数——三次函数。双三次函数可以表示为:
方法5 - 约束双三次插值 通过在每个数据点强制部分导数和交叉导数为0,可以修改双三次算法。
代码实现 文件interp2.h包含了上述所有算法的实现:
// Nearest neighbor interpolation
template<typename T>
void nni(const Matrix<T> &in, Matrix<T> &out)
// Bilinear interpolation
template<typename T>
void bilin(const Matrix<T> &in, Matrix<T> &out)
// Biquadratic interpolation
template<typename T>
void biquad(const Matrix<T> &in, Matrix<T> &out)
// Bicubic interpolation
template<typename T>
void bicube(const Matrix<T> &in, Matrix<T> &out)
// Constrained bicubic interpolation
template<typename T>
void cbi(const Matrix<T> &in, Matrix<T> &out)
所有这些方法都需要某种矩阵表示数据。强烈建议在任何严肃的工作中使用专业的矩阵代数包。除非是喜欢重新发明轮子的天才,否则不要自己编写。个人的偏好是Eigen,但有很多选择。