添付のような魚眼加工ができないか試しているのですが、どうもうまくいきません。imagemagickでどのようなconvert文を実行すれば良いか教えてもらえないでしょうか?
また、計算式が複雑な場合、簡単な解説もつけて頂けると助かります。
何らかの中間画像が必要なのかもしれないですが・・・。
まず小手調べ、というか画像の確認。
画像の中心から短辺で接する円を変換対象にすることにします。
convert -fx "kk=w*0.5;ll=h*0.5;sr=min(kk, ll);dx=i-kk;dy=j-ll;rr=hypot(dx,dy);rr < sr ? p{dx+kk,dy+ll} : 0" in out
変換式はこんな感じ。
convert -fx "kk=w*0.5;ll=h*0.5;sr=min(kk, ll);dx=i-kk;dy=j-ll;rr=hypot(dx,dy);pr=1-2*acos(rr/sr)/pi;px=(rr==0.0 ? 0.0 : pr*dx*sr/rr);py=(rr==0.0 ? 0.0 : pr*dy*sr/rr); rr < sr ? p{px+kk,py+ll} : 0" in out
計算……全部自分でやりました。
http://www.nikon-image.com/enjoy/interview/historynikkor/2000/0010/
正射影の説明はここで読みました
変換の感じをイメージするには、まず半円柱を使った射影を考えた方がいいのかなぁ、と思いました。
画像を半円柱にペッタリとくっつけたときに、変換先の画素から見て《真上》の変換元の画素を求めればよい、と。(左上の図)
これを半球に拡張すると、画像をペッタリと半球にくっつけることはできないので、極座標的な考え方をした方がよさそうです。
さて、画像の座標は左上が0,0です。これだと不便なので、画像の真ん中を0,0にした座標にして考えます。
これが計算中に出てくるdx,dyですね。
でも紙に書いていたときはまだxx,yyって書いてますね。実際の式ではdx,dyです。
あと紙とここの回答にrと書いているのは、実際の式でsrにしてます。
のちのちは頻繁に出てくるので式ではrrに代入してます。
変換先の点(dx,dy)に射影される点をさがすのに、(dx,dy)から見て真上に射影した球面上の点と、半球面の中心、そして中心の直上の点を通る断面を考えます。
いや、z軸と点(dx,dy)を通る断面、と言った方がわかりやすいでしょうか。
点(dx,dy)の直上の球面上の点Sはで表せます。(右上の図)
断面を持ってきます。(右側上から2番目)
になりますから、
です。式中のacosがcosの逆関数です(ていうかtex記法でacosって書くとcos^(-1)の記号になる。なんでww)。
この4分円の弧を、ぐいっ、と引き延ばします。
の直線です。おっと、-fxで扱う角度がラジアンなのでここでもラジアンで書きますよ。
点Sの右側がですので、左側はです。
この線分を変換元画像に持ってきます。
左側を中心に、点(dx,dy)を通る角度での射影を考えます。長さは違うので同じ比で分割したときに点Sにあたる点を探します。(右下の円)
変換元画像の外周上の点は、です。
比率をかけることで変換元の対応する画素を計算しました。
原点(dx=0,dy=0)付近で0割りが発生するので、rr==0.0 かどうかをチェックしています。
こんな感じでしょうか。
convert hoge.jpg -fx 'kk=w*0.5;ll=h*0.5;dx=(i-kk);dy=(j-ll);aa=atan2(dy,dx);rr=hypot(dy,dx);rs=rr*rr/hypot(kk,ll);px=kk+rs*cos(aa);py=ll+rs*sin(aa);p{px,py}'
それすると等距離投影が混じってくる気がします。
元は透視投影なのでタンジェントで変換すると
http://www.wolframalpha.com/input/?i=tan%28Pi%2F2-acos%280.8x%29%29%2Ftan%28Pi%2F2-acos%280.8%29%29%2C+x+from+0+to1
となる気がします。で、これは下記と等価です。
http://www.wolframalpha.com/input/?i=0.6x%2Fsqrt%281-0.64x%5E2%29%2C+x+from+0+to+1
実際の式で書くと
pr=1-2*acos(rr/sr)/pi
が
pr=0.6/sqrt(1-0.64*(rr/ll)^2)
になるかと。
0.64は0.8^2、0.6はsqrt(1-0.8^2)で、0.8は半周180度に対する画角の比にあたります。
ただ、実際は写した段階で周辺部に歪みが出ているので細かい所は気にしなくてもいいのかもしれません。
あと、本当は2次方程式に近似してやるとimagemagicの機能でもっと効率よく計算出来るのかもしれません。
ただ、その辺は良く分かってないのでポインタだけ...
http://www.imagemagick.org/Usage/lens/
元はレンズによる歪みを補正する機能だと思うけど、うまく使えば逆変換できるんじゃないかと。