前回の続きです。
ただ、私としては台形に変形させたいので、8次元連立一次方程式を解いた方式をさらに模索していた中で、下記サイトを見つけました。
射影変換(ホモグラフィ)について理解してみる - デジタル・デザイン・ラボラトリーな日々
ホモグラフィ(CSS3 Transform 3D Test)- Shogo Computing Laboratory
内容的には私が目指していたものですが、残念なのは中身はCSSなんですよね。
先ず下記の8次元連立一次方程式を解く方法ですが、これには行列を使えばいいことが分かりました。
変換前の座標 左上から時計回り
変換後の座標 左上から時計回り
8次元連立一次方程式
これを行列式に変換します。
CSSを使用したホモグラフィのソースリストを見ても、変換元座標(origin)と変換先座標(markers)で4点分ループして行列式を作成していますね。
var i, M = [], V = []; var x, y, X, Y; for(i=0;i<4;i++) { x = origin[i][0]; y = origin[i][1]; X = markers[i].x() - imgx; Y = markers[i].y() - imgy; M.push([x, y, 1, 0, 0, 0, -x*X, -y*X]); M.push([0, 0, 0, x, y, 1, -x*Y, -y*Y]); V.push(X); V.push(Y); }
変換元座標(origin)と変換先座標(markers)から8個のパラメータを求める必要があります。
それには逆行列(inverse)を使います。
からパラメータを求めるにはの逆行列を掛ければいいので、となります。
逆行列については、「逆行列を理解してみる」を参照
Javascriptには標準では行列ライブラリがありませんが、このプログラムでは"sylvester"の"sylvester-min.js"という代数ライブラリを使用しております。これは記法も凄く短くて、 $V() でベクトル生成、$M() でマトリクス(行列)生成となっております。
行列計算によって、8個のパラメータ(a,b,c,d,e,f,g,h)は、ans.e(1)~ans.e(8)として値が求まりました。
var ans = $M(M).inv().x($V(V));
console.log($M(M).inspect());
console.log($V(V).inspect());
console.log(ans.inspect());
8個のパラメータから台形等に変形した画像にしているのが下記の部分です。
上記まではCSSではなくJavascriptであるため、Canvasに移植する上では問題ないのですが、Canvasではmatrix3dのような画像変形は自前で処理する必要があります。
var transform = "perspective(1px)scaleZ(-1)translateZ(-1px)matrix3d(" + ans.e(1) + ',' + ans.e(4) + ',' + ans.e(7) + ',0,' + ans.e(2) + ',' + ans.e(5) + ',' + ans.e(8) + ',0,' + ans.e(3) + ',' + ans.e(6) + ',1,0,' + '0,0,0,1)translateZ(1px)'; }
次回は、画像変形処理について解析していきます。