Free-Form Deformation(FFD)を使用して2D画像の変形を行おうと試みているが、FFDはベジエ(Bezier)曲面で表される座標系を使用して変形する。
そこで、ベジエ曲線を復習を兼ねてmatplotlibで描画してみる。
ベジエ曲線を2次元に拡張するとベジエ曲面となる。
まずは、単純なベジエ曲線を描画する。
Pythonのコード例
import scipy.misc as scm import numpy as np import matplotlib.pyplot as plt def bernstein(n, i, t): return scm.comb(n, i) * t**i * (1 - t)**(n-i) def bezier(n, t, q): p = np.zeros(2) for i in range(n + 1): p += bernstein(n, i, t) * q[i] return p q = np.array([[0, 0], [1, 1], [4, -1], [5, 0]], dtype=np.float) list = [] for t in np.linspace(0, 1, 100): list.append(bezier(3, t, q)) P = np.array(list) plt.plot(P.T[0], P.T[1]) plt.plot(q.T[0], q.T[1], '--o') plt.show()
二項係数は、scipy.misc.combを使用して計算している。
上記のコード例では、制御点の次数は3で、制御点(0, 0)、(1, 1)、(4, -1)、(5, 0)によって表されるベジエ曲線を描画している。
なお、list.appendの部分をリスト内包を使ってもう少しスマートに書くと、
P = np.array([bezier(3, t, q) for t in np.linspace(0, 1, 100)])
のように記述できる。
bezier関数でΣの計算にforを使用しているが、以下のようにリスト内包と行列の積を使用しても記述できる。
np.dot([bernstein(n, i, t) for i in range(n + 1)], q)
numpyの行列は、横ベクトルなので、行列の積を計算する際は間違わないように注意が必要である。
実行結果