人力検索はてな
モバイル版を表示しています。PC版はこちら
i-mobile

imagemagickで先日いろいろと教えて頂いた-fxオプションを使って、
添付のような魚眼加工ができないか試しているのですが、どうもうまくいきません。imagemagickでどのようなconvert文を実行すれば良いか教えてもらえないでしょうか?
また、計算式が複雑な場合、簡単な解説もつけて頂けると助かります。
何らかの中間画像が必要なのかもしれないですが・・・。

1347662738
●拡大する

●質問者: MrB
●カテゴリ:コンピュータ インターネット
○ 状態 :終了
└ 回答数 : 3/3件

▽最新の回答へ

1 ● oil999
●10ポイント

こんな感じでしょうか。

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}'

MrBさんのコメント
回答ありがとうございます。 これが先日教えて頂いたものなのですが、画像が丸くならないので、どうしたら丸くなるかを知りたいと思っています。

2 ● TransFreeBSD
●30ポイント

先日の式は、描画点を一旦極座標系に変換し、描画点の距離rrを、「rs=rr*rr/hypot(kk,ll)」で読取点の距離rsに変換し、XY座標に戻す、ということをやっているようです。
さて、魚眼レンズへの変換ですが、原理については下記がわかりやすかったです。
http://odabouta.blog115.fc2.com/blog-entry-10.html
いくつかありますが、等距離射影の「r*θ」がわかりやすいのでこれを採用します。
あと、通常の写真にあたる透視投影がないのですが、これは焦点距離をrとすると「r*tanθ」になるかと思います。

いま、透視投影の写真から点を読取り、等距離投影で描画することを、極座標の距離についてのみ考えます。
読取点rsは透視投影ですので「rs=r1*tanθ」となります。
また、描画点rrは等距離投影ですので「rr=r2*θ」となり「θ=rr/r」となります。
したがって「rs=r1*tan(rr/r2)」が変換式になります。
f:id:TransFreeBSD:20120915153856j:image
さて、r1,r2について考えます。
「rs=r1*tanθ」より透視投影の元画像でθ=45°(視野角でいうと倍の90°)の時に「rs=r1」となります。
つまり視野角90°の半径に相当するピクセル数がr1になります。
この視野角90°(π/4)のときの描画半径が「rr=r2*(π/4)」となります。
このあたりは適当に調整してみることになるんじゃないでしょうか。

ちなみに、どうあがいても、元の画像は視野角が180°よりかなり狭いので、魚眼レンズ風にしても、周辺部分はカットするかごまかすことになると思います。



と、ここまで書いてあれですが、たぶんあっていると思う。


MrBさんのコメント
回答ありがとうございます。 頂いたURLの「正射影」を実現したいのですが、 具体的にどのような計算式で変換後の座標を 求めればいいかわからず苦戦しています。 x、y座標での計算式をお教えいただければ幸いです。

質問者から

質問が分かりずらくて、すみません。
一番知りたいのは、
添付のbeforeからafterの画像を作る場合
imagemagickのconvertの-fxオプションで
どのように記述すれば良いかということです。


3 ● quintia
●200ポイント ベストアンサー

まず小手調べ、というか画像の確認。
画像の中心から短辺で接する円を変換対象にすることにします。

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

計算……全部自分でやりました。
f:id:quintia:20120915222725j:image:medium

http://www.nikon-image.com/enjoy/interview/historynikkor/2000/0010/
正射影の説明はここで読みました

変換の感じをイメージするには、まず半円柱を使った射影を考えた方がいいのかなぁ、と思いました。
画像を半円柱にペッタリとくっつけたときに、変換先の画素から見て《真上》の変換元の画素を求めればよい、と。(左上の図)

これを半球に拡張すると、画像をペッタリと半球にくっつけることはできないので、極座標的な考え方をした方がよさそうです。

さて、画像の座標は左上が0,0です。これだと不便なので、画像の真ん中を0,0にした座標にして考えます。
これが計算中に出てくるdx,dyですね。
でも紙に書いていたときはまだxx,yyって書いてますね。実際の式ではdx,dyです。
あと紙とここの回答にrと書いているのは、実際の式でsrにしてます。
のちのち¥sqrt{dx^2+dy^2}は頻繁に出てくるので式ではrrに代入してます。

変換先の点(dx,dy)に射影される点をさがすのに、(dx,dy)から見て真上に射影した球面上の点と、半球面の中心、そして中心の直上の点を通る断面を考えます。
いや、z軸と点(dx,dy)を通る断面、と言った方がわかりやすいでしょうか。
点(dx,dy)の直上の球面上の点Sは(dx, dy, ¥sqrt{r^2-(dx^2+dy^2)})で表せます。(右上の図)

断面を持ってきます。(右側上から2番目)
cos¥theta=¥frac{¥sqrt{dx^2+dy^2}}{r}になりますから、
¥theta=acos(¥frac{¥sqrt{dx^2+dy^2}}{r})です。式中のacosがcosの逆関数acosです(ていうかtex記法でacosって書くとcos^(-1)の記号になる。なんでww)。

この4分円の弧を、ぐいっ、と引き延ばします。
¥frac{¥pi}{2}rの直線です。おっと、-fxで扱う角度がラジアンなのでここでもラジアンで書きますよ。
点Sの右側が¥theta rですので、左側は(¥frac{¥pi}{2}-¥theta)rです。

この線分を変換元画像に持ってきます。
左側を中心に、点(dx,dy)を通る角度での射影を考えます。長さは違うので同じ比で分割したときに点Sにあたる点を探します。(右下の円)
変換元画像の外周上の点は、(¥frac{dx}{¥sqrt{dx^2+dy^2}}r, ¥frac{dy}{¥sqrt{dx^2+dy^2}}r)です。
比率¥frac{(¥frac{¥pi}{2}-¥theta)r}{¥frac{¥pi}{2}r}=1-¥frac{2}{¥pi}¥thetaをかけることで変換元の対応する画素を計算しました。

原点(dx=0,dy=0)付近で0割りが発生するので、rr==0.0 かどうかをチェックしています。


MrBさんのコメント
完璧な回答ありがとうございました。 知りたいことがすべてかかれてました。 長らく数学をやってないと駄目ですね。 円周=2πr、180度=2πなどもすっかり忘れてました。 計算もありがとうございました。 また機会があればお願いします。
関連質問

●質問をもっと探す●



0.人力検索はてなトップ
8.このページを友達に紹介
9.このページの先頭へ
対応機種一覧
お問い合わせ
ヘルプ/お知らせ
ログイン
無料ユーザー登録
はてなトップ