【画像処理】メモ:平面射影変換

平面射影変換(四角から台形への変換とか)の変換式は以下。
u = (p1 * x + p2 * y + p5) / (p7 * x + p8 * y + 1)
v = (p3 * x + p4 * y + p6) / (p7 * x + p8 * y + 1)

分母を払い、パラメータpに関する一次式の形にする。
u = (p1 * x + p2 * y + p5) - p7 * x * u - p8 * y * u
= (x, y, 0, 0, 1, 0, -x*u, -y*u) (p1, p2, p3, p4, p5, p6, p7, p8)^T
v = (p3 * x + p4 * y + p6) - p7 * x * v - p8 * y * v
= (0, 0, x, y, 0, 1, -x*v, -y*v) (p1, p2, p3, p4, p5, p6, p7, p8)^T

未知数が8個なので、4点の座標の対応関係が分かれば連立方程式より
pが求まる。
4点の情報を集めれば以下の行列の方程式の形になる。
|u1| |x1, y1, 0, 0, 1, 0, -x1*u1, -y1*u1| |p1|
|v1| |0, 0, x1, y1, 0, 1, -x1*v1, -y1*v1| |p2|
u2| |x2, y2, 0, 0, 1, 0, -x2*u2, -y2*u2| |p3|
|v2|=|0, 0, x2, y2, 0, 1, -x2*v2, -y2*v2|.|p4|
|u3| |x3, y3, 0, 0, 1, 0, -x3*u3, -y3*u3| |p5|
|v3| |0, 0, x3, y3, 0, 1, -x3*v3, -y3*v3| |p6|
|u4| |x4, y4, 0, 0, 1, 0, -x4*u4, -y4*u4| |p7|
|v4| |0, 0, x4, y4, 0, 1, -x4*v4, -y4*v4| |p8|


簡単に書くと、
u = A.p
よって、パラメータpは以下Aの逆行列をかければ求まる。
p = A^-1 . u

【例】
例えば対応関係が以下の場合には、

変換後   変換前
(x1,y1)<->(u1,v1)=(0, 0)<->( 0, 0)
(x2,y2)<->(u2,v2)=(0, 128)<->( 0, 128)
(x3,y3)<->(u3,v3)=(64, 30)<->(128, 0)
(x4,y4)<->(u4,v4)=(64, 98)<->(128, 128)

この場合、パラメータは
p={1.0625, 0, -0.46875, 1, 0, 0, -0.00732421875, 0}となる。
行列演算はmatlabmathematica、行列演算関数でも使ってください。

結果例。補間はlanczosを使ってます。左が入力。右が変換後。