imagemagickで魚眼レンズ風に加工したいと思い、ネット検索して、

以下の記述を見つけました。

convert -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}" infile outfile

しかしfxの中身がいまいちよく分からないので、教えて頂ければ幸いです。
wは画像の横幅、hは画像の縦幅というのは分かるのですが、
iのcolumn offsetやjのrow offsetがよく意味が分かりません。
atan2やhypotやsinは数学の関数なので、わかるのですが、
最後のp{px,py}が何を意味してるのかが良くわからない状況です。

回答の条件
  • 1人5回まで
  • 登録:
  • 終了:2012/09/14 13:36:30
※ 有料アンケート・ポイント付き質問機能は2023年2月28日に終了しました。

ベストアンサー

id:quintia No.1

回答回数562ベストアンサー獲得回数71

ポイント100pt

-fx は、画像の全ピクセル分、指定した式を計算することでそのピクセルの値(=色)を決めるオプションです。

指定した式は、書き出し先の画像のピクセル数分繰り返し計算されます。
例えば100×50ピクセルの画像を書き出すときは5000回計算することになります。
元画像の色情報を参照するuを使って、

convert -fx "u*0.5" in out

とすると、元画像を暗くした画像ができます。
書き出した画像は全ピクセルについて、元画像の色情報×0.5 という計算を行ったことになります(0が黒、1.0が白なので0.5倍すると暗くなる)。

iを使ってみます。

convert -fx "u * i/w" in out 

左の方が暗くなるグラデーション画像になります。
iはピクセルの横方向座標を参照する式です。
一番左のピクセルについて計算している時iを参照すると0、一番右のピクセルの時iを参照するとw-1になっています(なので本当はw-1で割るべき? まあざっくりということで)。

jは縦方向の座標を参照します。左上を原点にして、同心円グラデーションするようにします。

convert -fx "u * sqrt(i^2+j^2)/sqrt(w^2+h^2)" in out 

sqrtは√です。sqrt(i^2+j^2)で¥sqrt{i^2+j^2}となって、つまりは原点(左上隅)からの距離ですね。
この距離を求めるのにhypotが用意されてますので、

convert -fx "u * hypot(i,j)/hypot(w,h)" in out 

でも同じです。

これだけだと元の画像の色を変える程度しかできません。
元の画像の別の場所のピクセルを参照するのがp{x,y}です。

convert -fx "p{w-1 - i, j}" in out 

イメージを左右反転します(i=0の時w-1-iがw-1、i=w-1の時w-1-iが0)。

id:MrB

丁寧な回答ありがとうございます。
とても分かりやすかったです。
また、機会がありましたらお願いします。

2012/09/14 13:37:22

その他の回答1件)

id:quintia No.1

回答回数562ベストアンサー獲得回数71ここでベストアンサー

ポイント100pt

-fx は、画像の全ピクセル分、指定した式を計算することでそのピクセルの値(=色)を決めるオプションです。

指定した式は、書き出し先の画像のピクセル数分繰り返し計算されます。
例えば100×50ピクセルの画像を書き出すときは5000回計算することになります。
元画像の色情報を参照するuを使って、

convert -fx "u*0.5" in out

とすると、元画像を暗くした画像ができます。
書き出した画像は全ピクセルについて、元画像の色情報×0.5 という計算を行ったことになります(0が黒、1.0が白なので0.5倍すると暗くなる)。

iを使ってみます。

convert -fx "u * i/w" in out 

左の方が暗くなるグラデーション画像になります。
iはピクセルの横方向座標を参照する式です。
一番左のピクセルについて計算している時iを参照すると0、一番右のピクセルの時iを参照するとw-1になっています(なので本当はw-1で割るべき? まあざっくりということで)。

jは縦方向の座標を参照します。左上を原点にして、同心円グラデーションするようにします。

convert -fx "u * sqrt(i^2+j^2)/sqrt(w^2+h^2)" in out 

sqrtは√です。sqrt(i^2+j^2)で¥sqrt{i^2+j^2}となって、つまりは原点(左上隅)からの距離ですね。
この距離を求めるのにhypotが用意されてますので、

convert -fx "u * hypot(i,j)/hypot(w,h)" in out 

でも同じです。

これだけだと元の画像の色を変える程度しかできません。
元の画像の別の場所のピクセルを参照するのがp{x,y}です。

convert -fx "p{w-1 - i, j}" in out 

イメージを左右反転します(i=0の時w-1-iがw-1、i=w-1の時w-1-iが0)。

id:MrB

丁寧な回答ありがとうございます。
とても分かりやすかったです。
また、機会がありましたらお願いします。

2012/09/14 13:37:22
id:Silvanus No.2

回答回数180ベストアンサー獲得回数71

ポイント100pt

先を越されてしまいましたね(汗)。
一番乗りさんのご回答と下記の画像を合わせてご覧いただければ
ご質問の命令文が何をしているのかお解りいただけると思います。

id:MrB

図入りの回答ありがとうございます。
各ピクセルを中心に寄せている感じですね。
これをもとに色々と応用を試してみたいと思います。
お二人ともベストアンサーにしたかったのですが、
どちらかしか選べなかったので、すみません。
せめてポイントは同じにさせて頂きました。
また、機会がありましたらお願いします。

2012/09/14 13:39:04
id:Silvanus

いえいえ!、お気になさらずw
各ピクセルを「中心に寄せている」のではなく
逆に「周辺へ移動させている」のです。
でないと魚眼レンズ効果になりませんしね!
つまり、(i,j)のピクセルを描記する際に
(px,py)のピクセルの色情報(p{,})を読みにいっているのです。
きっと僕の図が、命令文に出て来る変数の順番に描かれているせいで
誤解を与えてしまったんだと思います。スミマセン。

2012/09/14 13:52:03

コメントはまだありません

この質問への反応(ブックマークコメント)

「あの人に答えてほしい」「この質問はあの人が答えられそう」というときに、回答リクエストを送ってみてましょう。

これ以上回答リクエストを送信することはできません。制限について

回答リクエストを送信したユーザーはいません