補間法

飛び飛びの値(表やサンプル)しか分かっていないときに、その間の値を推定する方法(補間)について説明します。

<注意>
このページでは、数式を表示するためにMathJaxを使用しています。ブラウザの設定でスクリプト実行をブロックしている場合、ページ内の数式が正しく表示されません。

補間とは

値が\(\ x = 0,\ 1,\ 2,\ \dots\ \)のところだけ分かっていて、その間(たとえば\(\ x = 2.3\ \))の値が必要になることがあります。

  • 三角関数の表を引くとき、表の刻みより細かい角度の値が必要になる。
  • 音のサンプルを、元と違う速さで再生する(サンプルとサンプルの間の値が必要になる)。
  • 絵を拡大して表示する。

分かっている点から、その間の値を推定することを補間と言います。
分かっている点を\(\ p_0,\ p_1,\ \dots\ \)とし、点\(\ i\ \)と\(\ i+1\ \)の間の位置を\(\ t\ \)(\(\ 0 \le t < 1\ \))で表します。

同じ8つの点を、4つの方法で補間したもの

最近傍補間

いちばん近い点の値をそのまま使います。

\[ f = \begin{cases} p_i & (t < 1/2) \\ p_{i+1} & (t \ge 1/2) \end{cases} \]

計算はいりませんが、値が階段状に変わります。
表を引くときに「小数部を四捨五入して表を引く」のは、この方法です。

線形補間

両側の2点を直線で結びます。

\[ f = p_i + (p_{i+1} - p_i)\,t = (1-t)\,p_i + t\,p_{i+1} \]

掛け算1回で済み、つながりに段差がなくなります。
ただし、点のところで折れ曲がります(傾きが急に変わります)。
コードでの書き方は、線形補間のレシピにあります。

誤差

定理
間隔\(\ h\ \)で並んだ点の線形補間と、元のなめらかな関数\(\ g\ \)との差は、

\[ \frac{h^2}{8}\,\max|g''| \]

を超えない(\(\ g''\ \)は\(\ g\ \)を2回微分したもの、つまり曲がり具合)。

誤差は間隔の2乗に比例するので、表の大きさを2倍にすると、誤差は1/4になります。
表をそのまま引く(最近傍補間)と、誤差は間隔に比例するので、表を2倍にしても誤差は1/2にしかなりません。

表の大きさと、正弦の表の誤差

1周を256に分けた正弦の表(256方位)を、そのまま引いたときの最大の誤差は約0.012ですが、線形補間すると約0.000075になります。
1周64の表でも、線形補間すれば誤差は約0.0012で、256の表をそのまま引くより10倍正確です。
表を小さくして補間するか、表を大きくしてそのまま引くかは、時間計算量と空間計算量の釣り合いで決めます。

多項式補間

\(\ n\ \)個の点をすべて通る\(\ n-1\ \)次の多項式は、ただ1つに決まります。
これを求めて間の値を計算する方法を多項式補間と言います。

定理 (ラグランジュ補間)
点\(\ (x_0,\ p_0),\ \dots,\ (x_{n-1},\ p_{n-1})\ \)をすべて通る多項式は、

\[ f(x) = \sum_{j=0}^{n-1} p_j \prod_{m \neq j} \frac{x - x_m}{x_j - x_m} \]

である。

2点なら直線(線形補間)、3点なら放物線になります。

点が多いときに、全部の点を通る1つの多項式を使うと、点と点の間で大きく波打つことがあります(ルンゲの現象)。

等間隔の11点を通る10次式

真ん中では元の関数によく合っていますが、両端では大きく外れています。
多くの点を補間するときは、全体を1つの式にせず、近くの数点だけを使う式を、区間ごとに切り替えて使います。

3次補間

区間の両側の2点に、さらに外側の1点ずつを加えた4点を使い、3次式でつなぎます。
よく使われるのは、次のキャットムル-ロムの式です。
\(\ p_{i-1},\ p_i,\ p_{i+1},\ p_{i+2}\ \)を\(\ P_0,\ P_1,\ P_2,\ P_3\ \)と書くと、次のようになります。

\[ f(t) = \frac{1}{2}\left( 2P_1 + (-P_0 + P_2)\,t + (2P_0 - 5P_1 + 4P_2 - P_3)\,t^2 + (-P_0 + 3P_1 - 3P_2 + P_3)\,t^3 \right) \]

この式は、各点を通り、さらに点\(\ P_1\ \)での傾きが\(\ (P_2 - P_0)/2\ \)(両隣を結ぶ直線の傾き)になるように作られています。
隣の区間とも傾きが揃うので、点のところで折れ曲がらず、なめらかにつながります。

同じ考え方で、点を通るなめらかな曲線を作る方法は、曲線で説明します。

2次元の補間

縦横に並んだ値(絵やマップの高さなど)の間を補間するには、横方向に線形補間したものを、さらに縦方向に線形補間します(双線形補間)。

\[ f = (1-t_y)\left((1-t_x)\,p_{00} + t_x\,p_{10}\right) + t_y\left((1-t_x)\,p_{01} + t_x\,p_{11}\right) \]

4×4の値を拡大したもの

最近傍補間ではマス目がそのまま大きくなり、双線形補間では、マス目の間がなめらかにつながります。
SNESのモード7の拡大は、最近傍補間にあたります(拡大すると、1つのピクセルがそのまま大きな四角になります)。

音の補間

サンプルを元より速く(高い音で)再生すると、1つの出力の間にサンプルがいくつも進み、遅く(低い音で)再生すると、サンプルの間の値が必要になります。

方法音の性質
最近傍補間階段状の波形になり、元の音にない高い成分(ザラザラした音)が加わる
線形補間折れ線になり、高い成分は少し減る
4点を使う補間なめらかになる。重みの付け方によって、高い成分の減り方が変わる

DSPは、前後4つのサンプルに重みを掛けて足す補間(ガウス補間)を使います(BRRの「ガウス分布補間」)。
補間は、高い成分を弱めるフィルタとしても働きます(サンプリングとデジタルフィルタ)。

参照

線形補間(65816のレシピ)
曲線
多項式近似
サンプリングとデジタルフィルタ
時間計算量と空間計算量