技術背景
插值法在圖像處理和信號處理、科學計算等領域中是非常常用的一項技術。不同的插值函數,可以根據給定的數據點構造出來一系列的分段函數。這一點有別於函數擬合,函數擬合一般是指用一個給定形式的連續函數,來使得給定的離散數據點距離函數曲線的總垂直距離最短,不一定會經過所有的函數點。比如在二維坐標系內,用一條直線去擬合一個平面三角形所對應的三個頂點,那么至少有一個頂點是不會落在擬合出來的直線上的。而根據插值法所得到的結果,一定是經過所有給定的離散點的。本文針對scipy和numpy這兩個python庫的插值算法接口,來看下兩者的不同實現方案。
插值算法
常用的插值算法比如線性插值,原理非常簡單。給定兩個點\((X_{t_0},Y_{t_0})\)和\((X_{t_1},Y_{t_1})\),其中\(t_0<=t_1\),假如需要計算點\((X_{t_2},Y_{t_2})\)的值,其中\(t_0<=t_2<=t_1\),那么給定的插值公式就是:
而還有一種比較常用的算法是三次樣條插值(cubic spline),其原理是在所有給定的\(n\)個離散點之間構建\(n-1\)個三次函數:
三次樣條插值的約束條件是給定的函數在端點處連續、給定函數的一次導數在端點處連續、給定函數的二次導數在端點處連續,再根據邊界條件的不同取法,可以構造出不同的三次樣條插值函數。如下圖所示就是三種不同的邊界條件取法(圖片來自於參考鏈接3):

接下來看下scipy中的線性插值和三次樣條插值的接口調用方式,以及numpy中實現的線性插值的調用方式(numpy中未實現三次樣條插值算法):
import numpy as np
from scipy import interpolate
import matplotlib.pyplot as plt
x = np.linspace(0, 4, 12)
y = np.cos(x**2/3+4)
int1 = interpolate.interp1d(x,y,kind='linear')
int2 = interpolate.interp1d(x,y,kind='cubic')
new_x = np.linspace(0, 4, 30)
plt.figure()
plt.plot(x,y,'o',color='black')
plt.plot(new_x,int1(new_x),'-',color='blue')
plt.plot(new_x,int2(new_x),'--',color='orange')
plt.plot(new_x,np.interp(new_x,x,y),'x',color='red')
plt.legend(['data','linear','cubic','numpy'],loc='best')
plt.savefig('_interpolate.png')
得到的結果如下圖所示:

在這個結果中我們發現,numpy的線性插值和scipy的線性插值所得到的結果是一樣的,而scipy的三次樣條插值的曲線顯然要比線性插值更加平滑一些,這也跟三次樣條插值算法本身的約束條件有關系。
總結概要
線性插值和三次樣條插值都是非常常用的插值算法,使用插值法,可以幫助我們對離散的樣本信息進行擴展,得到樣本信息中所不包含的樣本點的信息。插值法有着非常廣泛的應用場景,就比如某手機廠商所號稱的x千萬像素拍照,其中插值法就發揮了重要作用。在python的scipy這個庫中實現了線性插值算法和三次樣條插值算法,而numpy庫中實現了線性插值的算法,我們通過這兩者的不同使用方式,來看下所得到的插值的結果。
版權聲明
本文首發鏈接為:https://www.cnblogs.com/dechinphy/p/interpolate.html
作者ID:DechinPhy
更多原著文章請參考:https://www.cnblogs.com/dechinphy/
打賞專用鏈接:https://www.cnblogs.com/dechinphy/gallery/image/379634.html
騰訊雲專欄同步:https://cloud.tencent.com/developer/column/91958