⚠️ これは 非公式の翻訳サイトです。ImageMagick Studio LLC とは無関係です。正確な情報は 原文(https://usage.imagemagick.org/distorts/index.html) を参照してください。

ImageMagick 使用例 -- 画像の歪み

IM が初期から提供してきた単純な組み込みの画像ラッピングおよび歪みオペレータを見てきましたが、ここではさらに踏み込んで、内部の仕組みと、より複雑な数学的画像歪みを見ていきます。この深い理解をもとに、より一般化された画像歪みオペレータへと進みます。これには、複雑な回転・拡大縮小・シアーから、透視あるいは3D歪み、円弧への/からのワーピング、カメラレンズの歪み、そして最終的にはよりモーフィングに近い一般的な歪みまでが含まれます。


一般的な歪み技法

IM が提供する単純な歪みオペレータを紹介したところで、一歩下がって細部を眺め、画像の歪みが実際にどのように働くのか、そしてその使い方をどう改善できるのかを見てみましょう。後ほど、ImageMagick に直接組み込まれていない手法も含め、はるかに複雑な画像の歪ませ方へと進んでいきます。画像処理が画像を歪ませる基本的な方法はわずかしかありません。たとえば 単純な歪み オペレータは ピクセルの入れ替え によって実現されます。すなわち、個々のピクセル、あるいはピクセルの行や列全体をただ入れ替えるだけで、画像の 反転ロール転置、さらには 矩形回転 を行います。色の変更は一切なく、ピクセル数も変わりません。次の画像歪み手法は、ピクセルの列と行を水平または垂直に シフトまたはシアー するもので、IM が 画像のシアー や上述の 波歪み で行っているものです。シアーはまた、任意の角度で 画像を回転 する一つの方法を、かなり高速に提供します。しかしピクセルシフト手法は、これら基本的な歪みに限られます。たとえば画像を別のサイズに拡大縮小することはできません。また、結果の画像のうち、元のソース画像で覆われなかった領域の扱いについても、ほとんど制御できません。上記の関数では、IM は欠落領域を現在の背景色に設定するだけです。画像をはるかに一般的な方法で歪ませるには、逆ピクセルマッピング として知られる、より一般的な歪み技法を使う必要があります。たとえばこの手法は、画像のインプロードスワール のような、より複雑な 円形歪み で使われています。

順方向(直接)ピクセルマッピング

画像を歪ませようとして最初に思いつくのは、ソース画像の各ピクセルをそのまま取って、宛先画像の新しい位置へ直接動かすことでしょう。実際、単純な歪み画像の切り抜き、さらにベクター画像の歪みでは、おおむねこれが行われています。各ピクセル(または座標)は最終画像内の新しい位置へとただ動かされます。残念ながら、これは単純な歪み以外を行おうとすると問題が生じます。たとえば、ここでは小さな画像の列挙ピクセルリストを取り、各ピクセルの位置を変えて新しい場所へ回転させてみます。 |

  # 17度回転 -- この角度の正弦と余弦を取得
  sin=`magick xc: -format "%[fx:sin( 17 *pi/180)]" info:`
  cos=`magick xc: -format "%[fx:cos( 17 *pi/180)]" info:`

  # 各ピクセルについて、そのピクセル座標を回転
  magick koala.gif  txt:- |  sed '2,$ s/,/:/' |\
    gawk -F: 'NR == 1 { print }
              NR > 1 {  x = $1-32;    y = $2-32;
                        nx = int( c*x - s*y + 32 );
                        ny = int( s*x + c*y + 32 );
                        printf( "%d,%d: %s\n", nx, ny, $3 );
              }' s=$sin c=$cos - |\
      magick -background black  txt:-   koala_rotated_direct.gif

[IM Output]
この歪みはわずか17度の単純な回転ですが、結果はまったくきれいではありません。まず、新しいピクセル位置はそれぞれ浮動小数点値になりますが、ピクセルは整数グリッド上にしか存在できないため、上のコードでは結果の非整数部分を単に捨てています。第二の問題は、どのピクセルも着地しなかった場所が穴だらけになることです。これが第三の問題につながります。見えないかもしれませんが、結果画像の穴一つひとつに対し、二つのピクセルが配置された場所も別にあるはずです。つまり、同じ位置に複数のピクセルがあるわけです。どのピクセル値を使えばよいのでしょうか。上の例では、IM はある位置に最後に定義されたピクセルを使っただけです。言い換えれば、結果画像は不完全で、宛先の各ピクセルは本来あるべき位置に正確にはなく、複数のピクセルがあったり、まったくなかったりします。これらは深刻な問題で、ソース画像から宛先画像へピクセルを順方向にマッピングする場合、容易には解決できません。とはいえ、これが不可能というわけではなく、多くの研究論文が 'スプラッティング' として知られる技法の利用について論じています。基本的には、各入力ピクセルを取り、その位置を変換し、新しい位置でピクセル色を適切に広げ混ぜながら描画します。この技法は、現実世界の物体を3Dデジタル化する際に特に有用です。ここでは色のわかった表面点の '雲' があり、ユーザーから見える任意の点を単にスクリーンに 'スプラット' して最終画像を作ります。点が十分にあれば、画像は完全に見えます。インタラクティブな3D制御と組み合わせれば、これは非常にうまく機能し、しかも高速です。しかし3次元の点をスプラッティングすることは、2Dラスター画像を扱う IM の範疇を超えています。

逆ピクセルマッピング

ピクセルを最終画像へマッピングしようとするのではなく、宛先画像の各ピクセルの座標をソース画像の対応する位置へマッピングし、そのソース画像からそのピクセルが持つべき色を調べることができます。これは 逆ピクセルマッピング として知られ、ほぼすべての画像歪みプログラムが行っていることです。宛先画像のあらゆるピクセルを処理する中で、宛先の各ピクセルがただ一つの色を必ず得ることを保証できます。したがって、各宛先ピクセルの 'ソース' 位置を割り出すことさえできれば、思いつくどんな数式を使ってでも、ソース画像を宛先画像へ歪ませられます。

[Diagram]

要約すると、歪みマッピング(逆マッピング)は次のことを行います。

宛先または出力画像の各ピクセル (I,J) について
   I,J のピクセル位置を元画像の X,Y ピクセル位置へマッピングする
   元画像の位置 X,Y の色を調べる
       色補間を用いて、適切な色を求める。
       あるいは実際のソース画像から外れた場合は、仮想ピクセル設定を用いる。
   宛先画像のピクセル I,J の色を設定する

上で変数名 'I,J' と 'X,Y' を使ったのは、これらの変数が FX DIY オペレータ で通常使う変数名に対応するためです。たとえばここでは、先ほど試したのと同じ17度回転をシミュレートしますが、今回は "[-fx](https://imagemagick.org/command-line-options/#fx)" オペレータを使って、その位置に最も近いピクセルをソース画像から調べます。 |

  # 17度回転 -- この角度の正弦と余弦を取得
  sin=`magick xc: -format "%[fx:sin( 17 *pi/180)]" info:`
  cos=`magick xc: -format "%[fx:cos( 17 *pi/180)]" info:`
  cx=37; cy=37;   # 回転の中心

  magick -size 75x75 xc:       koala.gif  \
          -virtual-pixel Black  -interpolate NearestNeighbor \
          -fx "ii = i - $cx;   jj = j - $cy;
               xx =  $cos*ii +$sin*jj + $cx;
               yy = -$sin*ii +$cos*jj + $cy;
               v.p{xx,yy}" \
          koala_rotated_fx.gif

[IM Output]
上記の DIY 例の詳細は、サブセクション DIY アフィン歪みマッピング でさらに確認できます。ご覧のとおり、宛先のあらゆるピクセルに色が調べられるため、画像に '穴' がなくなりました。まだあまりきれいには見えませんが、それは各ピクセルにどの色を正確に置くべきかを調整する問題です。つまり、逆ピクセルマッピングは穴も重複ピクセルも生じません。各ピクセルが適切に定義された色を持ち、完全な画像が作られます。
順方向マッピングと逆マッピングの区別は重要です。なぜなら、ほとんどの数学的変換は順方向マッピング、すなわち単一のソース (X,Y) 位置を宛先 (I,J) 位置へマッピングするものとして定義されているからです。実際 '順方向マッピング' は、線の端をマッピングして描くだけでよいベクターグラフィックスや線の描画ではうまく機能します。これは、線が直線のまま保たれる回転のような線形変換では特に当てはまります。実際それは、postscript や SVG のようなベクターベース言語すべてで行われていることです。しかし一般的なラスター画像の場合、宛先画像のすべてのピクセルを確実に '埋める' ために、'逆マッピング' を使って画像を歪ませなければなりません。たとえば上の二つの例で座標をマッピングするのに使われた数式を見れば、それらがほとんどまったく同じであることがわかるでしょう。'回転' の逆マッピングは、逆方向の別の '回転' です。よく見ると、'sin' 定数が順方向版に対して符号反転されており、それだけで回転方向が逆になっていることがわかります。この詳細は重要かつ決定的です。問題は、すべての順方向マッピング変換が逆変換としてうまく機能するわけではないことです。実際、いくつかの順方向マッピングには単純な直接の逆マッピングがありません。これはできないという意味ではなく、ただ単純ではないということです。一方で、逆マッピングとしては非常にうまく機能するのに、単純な順方向マッピングを持たない画像変換もあります。したがって逆マッピング手法を使うことは、数学的には良くもあり悪くもあります。
参考までに、上記と同じ画像の回転を行い、まったく同じ結果をより高速に生成する、一般的歪み SRT 手法を使った上記の高速な等価例を示します。ここでも色の参照は、'point' 補間を用いてマッピング位置に最も近いピクセルの色のみに制限されています。つまり(ソース画像から '外れた' 場合を除いて)画像に新しい色は追加されませんが、激しいエイリアシング効果も生じます。 |

  magick koala.gif  -virtual-pixel Black  -interpolate NearestNeighbor \
          -filter point    -distort SRT 17    koala_rotated_srt.gif

[IM Output]
| 歪み変換についての別の解説は、Leptonica, Affine Implementation と、特にその 'point-wise' 手法の議論を参照してください。もう一つの手法 'sequential' は、本質的に IM がかつて 回転シアー 歪みオペレータを実装していた方法です。
---|---
名前には何がある? 研究の中で、私はこの画像処理手法に明確な名前付けが存在しないことに気づきました。実際のアルゴリズム的プロセスは '逆ピクセルマッピング' として知られ、数式の使用は '幾何学的変換' として知られています。歪みがさまざまな制御点の移動によって制御される場合、しばしば '画像ワーピング' または 'ラバーシーティング' と呼ばれます。通常は二つ以上の画像間の等価な点を見つけるために特定の点を定義するプロセスは、'画像レジストレーション' として知られています。画像はまた、より小さく単純な単位に細分化し、'グリッディング'(四辺形)や '三角メッシュ'(三角形)という技法を用いて個別に歪ませることもできます。二つの画像からの色のブレンドを伴う小さな漸進的歪みを使えば、映画やミュージックビデオで見るような、アニメーション化された 'イメージモーフ' を生成できます。その場で数式により参照する代わりに、あらかじめ用意したマッピング画像を使うと、'絶対歪みマッピング' になります。参照が相対変位(50% グレーが変位なし、つまり参照座標の変更なし)であれば、'変位マッピング' になります。マッピングが歪みの参照ではなく、わずかに色(陰影)を変更するだけなら、関連はするが別物の 'バンプ面マッピング' になります。3D モデリングや3D コンピューターゲームでは、同じ技法が、'テクスチャマッピング' として知られる方法で、平面や曲面に何らかの色付きパターンを与えるためにも使われます。これは画像を単一ピクセルに迫るグリッドやメッシュに細分化することを伴う場合があります。さらに、'ポイントスプラッティング' という技法を用いて、数百万の単一点で定義された物体を見ることもできます。ただしこれは通常、順方向マッピング歪みを用いて適用されます。上記すべては非常に密接に関連しており、ほとんどは基本的に、最終的な宛先座標をソース画像(または物体)へマッピングすることに基づいて、ピクセルの色を参照することを伴います。言い換えれば、宛先からソースへ のマッピングです。どの用語を使うべきか… お好みでどうぞ。

ピクセルの色参照

上記の 逆ピクセルマッピング 技法には、まだいくつか問題があります。まず第一に、宛先の固定された整数位置からピクセルをマッピングすると、ソース画像内では非整数位置になることがあります。すなわち、ソース画像上の個々のピクセルの間のどこかに落ちる位置です。どの色を返すべきかを決めるために、補間 というプロセスを用いて、その実数位置の最終的な色を、周囲のピクセルの色を混ぜることで決定します。補間 設定はまた、歪んだ画像の一部が '引き伸ばされ'、単一のソースピクセルが宛先画像の広い領域に滲み広がる場合も処理します。しかしその逆は、単純な補間手法ではうまく処理されません。それには別の技法が必要で、それを以下で見ていきます。たとえばここでは再びコアラを回転させますが、今回は "[-interpolate](https://imagemagick.org/command-line-options/#interpolate) [Mesh](misc.html#mesh)" 設定を使って近傍の4ピクセルを混ぜ、参照からより良い、より正確な色を生成します。 |

  magick koala.gif  -virtual-pixel Black  -interpolate Mesh \
          -filter point    -distort SRT 17    koala_rotated_mesh.gif

[IM Output]
ご覧のとおり、非整数の参照点を取り囲む最も近い近傍色を単純に統合するだけで、歪んだ画像の見た目を大きく改善できます。しかし、ほかにも問題があります… たとえば、マッピングされた位置がソース画像を完全に '外した' 場合はどうするのでしょうか。この場合、どの色を返すべきかは 仮想ピクセル 設定によって決まります。この設定は、ソース画像の最も近い端の色を選んだり、ソース画像が平面全体に無限にタイル状(あるいはミラータイル状)に並んでいると見なしたり、'白'、'黒'、'透明' などの特定の色やユーザー定義の背景色を使ったりします。さらに、マッピングされる特定の宛先位置に対して、数学的に有効な座標が存在しない可能性もあります。たとえばピクセルが透視 '平面' の '空' を見ている場合(遠い地平線を眺める を参照)、ソース画像のある平面すら見ていないことになります。この場合、仮想ピクセル は役に立ちません。なぜなら、N次元空間でソース画像平面に 'ヒット' しないため、その結果その宛先ピクセルは完全に無効なのです。この場合 IM は、現在の "[-alpha set](https://imagemagick.org/command-line-options/#alpha)" 設定をそのピクセルの色に使います。'ニアミス' であれば、IM は画像平面の近傍色とこの無効な色をアンチエイリアスします(その方法がわかる場合)。透視歪みについてはそれを行います。

スーパーサンプリング

補間は単純な画像歪みではうまく機能します。しかし、ソース画像の一部がはるかに小さな領域に圧縮される場合、各宛先ピクセルは実際にはソース画像のはるかに広い領域の統合を必要とすることがあります。ピクセルは本当は点ではなく、実画像の矩形領域を表していることを思い出してください。これは、場合によってはソース画像の広い領域を単一の宛先ピクセルに圧縮しようとすべきことを意味します。これが起きると、単純な ピクセル参照 は失敗します。なぜなら、それはソース画像内の単一の '点' の色(周囲のピクセル近傍を使って)を調べるだけで、その単一ピクセルに圧縮されなければならない入力画像のすべての色を混ぜ合わせ統合しないからです。その結果、宛先ピクセルは、関与する色すべての平均ではなく、ソース画像から本質的にランダムな色になってしまう可能性があります。これ自体は悪いことではありませんが、ある領域のすべてのピクセルでこれが起きると、一見ランダムで孤立したピクセル、モアレ効果、エイリアス化した '階段状' 効果のある画像になります。細い線も点線や破線のように見え始め(Sample オペレータ の例を参照)、あるいは完全に消えてしまうこともあります。これらすべての効果は総称して エイリアシングアーティファクト として知られています。これに対する一つの解決策は、宛先のあらゆるピクセルについてソース画像からより多くの色を参照し、宛先画像の各ピクセルのより正確な色を割り出そうとすることです。最も単純な解決策は一般に スーパーサンプリング、または オーバーサンプリング として知られています。Super-Sampling に関する Wikipedia の項目 を参照してください。各宛先ピクセルにマッピングされる領域全体でソース画像からより多くのサンプルを取ることで、そのピクセルの最終的な色は、その点での歪んだ画像をより正確に表すものになります。色のサンプルを多く取るほど、最終的な色はより正確になり、より滑らかで写実的な見た目になりますが、歪みは遅くなります。この技法は、ソース画像が50%以上圧縮される領域で、宛先の全体的な見た目を本当に改善するだけだということを覚えておいてください。歪みがソース画像を拡大する領域や、おおよそ同じ縮尺を保つ領域では、ソース画像の単一の 補間参照 で、たった一回の参照だけで一般に良い結果が得られます。画像のインプロード ワーピングの例(および IM 使用例の他の多くの例)では、'スーパーサンプリング' の最も単純な手法に簡単に触れました。基本的には、出力画像のサイズ(この場合は単に入力画像)を拡大してから歪みを行います。歪みが完了したら、画像を通常のサイズに戻してリサイズし、生成された余分な 'サンプル' すべてを統合します。たとえば…

  magick -size 94x94 xc:red -bordercolor white -border 3 \
          -virtual-pixel tile                -implode 4 \
          implode_tiled_box.gif
  magick -size 94x94 xc:red -bordercolor white -border 3 \
          -virtual-pixel tile  -resize 400%  -implode 4 -resize 25% \
          implode_tiled_ss.gif

[IM Output]
箱画像の通常のインプロージョン | [IM Output]
スーパーサンプリングしたインプロージョン
---|---

もちろん入力画像を拡大する代わりに、より高品質な(より大きな)ソース画像から始めることも、それ以前の処理ステップで一つ生成することもできます。もし利用できるなら。これはテキストの回転で特に有用です。テキストはしばしば非常に細かいディテールを持ち、最終画像で良い高品質な見た目を保つために、それを均一に保存する必要があるからです。この例については Polaroid 変換 を参照してください。 IM v6.4.2-6 以降、一般歪みオペレータ は拡大された出力画像を直接生成でき、それをスケール(またはリサイズ)して縮小し、結果のピクセルを統合・スーパーサンプリングできます。歪みスケール設定 および次の例を参照してください。
これは スーパーサンプリング の一手法('グリッド' 法として知られる)にすぎず、この手法には他にも多くのバリエーションがあります。いずれはこれらの手法が ImageMagick によりじかに実装されるかもしれませんが、今のところ単純な画像の拡大とスケーリングが、追加のコーディングを一切必要とせずかなりうまく機能します。最後に一つ警告を。スーパーサンプリングは、最終画像の各ピクセルに使われたサンプル数、ひいては最終リサイズで使われるスケーリング量によって制限されます。これが歪んだ画像の最終的な '品質' を決めます。しかし、より大きなスケーリング係数を使うと、歪んだ画像の生成はもちろんはるかに遅くなります。とはいえより高い品質を得るにも、限界があります。極端な場合、スーパーサンプリングは(インプロードされた画像の中心のような)無限を伴うどんな画像歪みも扱えません。そのような場合には、エリアリサンプリング(後述)が提供するような、まったく別の技法が必要になります。要約すると、スーパーサンプリングは、回転、シアー、アフィン、単純な透視のような、わずかな歪みだけを持つ画像の見た目を改善できます。しかし、改善できる歪みの種類には限界があります。適応的スーパーサンプリング スーパーサンプリング技法はさらに拡張できます。各ピクセルに固定数の色参照を使うのではなく、ソース画像内の参照間の距離、あるいは低レベルサンプリングから返される色の近さをチェックして、その特定のピクセルにもっとサンプルを取るべきかを確認します。すなわち、歪みの詳細について何も知らなくても、スーパーサンプリングの量を歪みの必要性に応じて調整できるのです。これは 適応的スーパーサンプリング として知られています。この技法は実際、レイトレーサーで非常に一般的です。レイトレーサーでは、特定の点で結果の画像がどれほど複雑かを判断するのがほぼ不可能だからです。この場合、もっとサンプルが必要なタイミングを決めるために、特定の位置周辺の '色差' の使用に制限されることがよくあります。あるピクセルが近傍と大きく異なるなら、その領域でもっとサンプルを使って、おそらく何らかの3次元物体の縁であろう部分を精細化します。IM は現時点では適応的スーパーサンプリングをサポートしていません。とはいえ、一般歪みオペレータ(後述)に別のサンプリング手法を追加することは十分可能です。コードの機能的な再編成が必要になるため、すぐには追加されないかもしれません。スーパーサンプリングのまとめ スーパーサンプリングの難しさは、どれだけの '点サンプル' が必要か、そしてそれらのサンプルをサブピクセル範囲内でどう配置すべきかを決めることにあります。また、どんな '重み付け' を適用すべきかも問題です。Super-Sampling に関する Wikipedia の項目 を参照してください。

より良い歪みのためのエリアリサンプリング

スーパーサンプリング手法の最良の代替案の一つが エリアリサンプリング です。より大きな画像を歪ませてリサイズで結果を平均する(これは画像からより多くのサンプルを取って平均するだけ)のではなく、各特定の出力ピクセルを生成するために(その点での歪みの '縮尺' に基づいて)ソース画像から実際にどれだけのピクセルを統合すべきかを正確に決定します。すなわち、各出力ピクセルがソース画像内で表すおおよその '領域' を割り出し、その領域内のすべてのピクセルを、リサンプリングフィルタに従って統合(フィルタリング)します。実際、これはまさに ImageMagick Resize オペレータ(実際には非常に特殊な種類の画像歪み)が、あれほど良い結果を生み出すために行っていることです。ただしリサイズの場合、各ピクセルでサンプリングが必要な領域の縮尺を計算するのは、画像全体に対して一度だけで済みます。サンプリングが必要な領域はソース画像内の固定サイズの矩形(ウィンドウ)なので、リサンプリングのプロセスが容易になり、歪みのプロセスに近道を提供します。歪んだ画像をエリアリサンプリングする場合、サンプルを取るピクセル領域(ウィンドウ)は位置だけでなくサイズも変わります。そのため、宛先の一つのピクセルはわずかなソース画像の色を統合するだけで済むことも、あるいは単一の補間色参照だけで済むこともあります(拡大の場合など)。一方で、宛先画像の別のどこかのピクセルは、正しい最終色を生成するために非常に多くのピクセルをサンプリングする必要があるかもしれません。無限に近い場合には、サンプリングのプロセスの一部としてソース画像のすべてのピクセルを含めなければならないことすらあります。また、宛先ピクセルがソース画像内で表す領域は、単純な正方形、円、あるいは楕円ですらなく、使われる歪みに応じて実際には非常に歪んだ形状になることがあります。そのような厄介な形状を計算し扱うのは、非常に時間がかかるか、達成がほぼ不可能になることがあります。[Diagram] ソース画像の楕円領域を使って各宛先ピクセルの色を計算する手法は、楕円加重平均(EWA)リサンプリングとして知られ、Paul Heckbert(彼はまた、実質的にすべての画像リサイズアルゴリズムの元となった 'zoom' プログラムも書きました)による PDF 研究論文 "Fundamentals of Texture Mapping and Image Warping" で概説されました。これがその後、新しい 一般化歪みオペレータ(後述)を定義するのに使われました。楕円は、アフィン歪み または 透視歪み のいずれにとっても完璧な形状です。極端な縮尺縮小(下の例を参照)には特に適しています。他の歪みには完璧ではないものの、円弧および極座標歪み(ただしその逆は除く)や、バレル歪み のような放射状歪みなど、他の多くの歪みにも一般に妥当な適合を示します。しかし DePolarShepards 歪み のような非線形歪みマッピングにはうまく適合しないため、これらの歪みには使われません。スーパーサンプルにはこの形状の問題がありません。なぜなら各 'サンプル' が宛先へ逆マッピングされるからです。そのため、そうした場合にはより良いサンプリング手法になります。ただし述べたように、必要なすべてのピクセルをサンプリングしなかったり、逆に多くサンプリングしすぎたりすることがあります。

エリアサンプリング対スーパーサンプリング

IM が現在提供する三つのサンプリング手法すべてを、極端な無限タイル状の透視画像に適用してみます。この歪みの詳細については、下の 遠い地平線を眺める を参照してください。

  # 入力画像: 金色の輪郭を持つ特別なチェッカーボード。
  magick -size 90x90 pattern:checkerboard -normalize -fill none \
          -stroke gold -strokewidth 3 -draw 'rectangle 0,0 89,89' \
          -fill red        -draw 'color 20,20 floodfill' \
          -fill lime       -draw 'color 40,70 floodfill' \
          -fill dodgerblue -draw 'color 70,40 floodfill' \
          checks.png

  # 補間参照を使用
  magick checks.png -filter point \
          -virtual-pixel tile -mattecolor DodgerBlue \
          -distort Perspective '0,0 20,60  90,0 70,63  0,90 5,83  90,90 85,88' \
          horizon_tile_point.png

  # グリッドスーパーサンプリングを使用
  magick checks.png  -filter point  -set option:distort:scale 10 \
          -virtual-pixel tile -mattecolor DodgerBlue \
          -distort Perspective '0,0 20,60  90,0 70,63  0,90 5,83  90,90 85,88' \
          -scale 10%    horizon_tile_super.png

  # エリアリサンプリングを使用(デフォルト)
  magick checks.png       -virtual-pixel tile -mattecolor DodgerBlue \
          -distort Perspective '0,0 20,60  90,0 70,63  0,90 5,83  90,90 85,88' \
          horizon_tile.png

[IM Output]
チェック画像 | | [IM Output]
補間
参照 | [IM Output]
スーパーサンプリング
x10 | [IM Output]
楕円加重エリア
(EWA)リサンプリング
---|---|---|---|---

上の画像はすべてまったく同じ歪みで、ただ異なる 'リサンプリング' 技法を使っているだけです。上の最後の画像は 一般化歪みオペレータ のデフォルト EWA 設定を使っており、ご覧のとおり極めて高品質な結果を生み出しました。ただし、この画像の生成には4.6秒かかりました。これは(関与する異常な極端さのため)やや遅いものの、それほど悪くはありません。最初の画像は、"[-filter](https://imagemagick.org/command-line-options/#filter) point" 設定を使ってデフォルトの EWA リサンプリングをオフにしています。これにより、各ピクセルに 直接補間参照 を使うよう強制されます。そのため、この画像は比較すると極めて高速に生成されましたが(0.51秒)、ご覧のとおり、'縮小'(ダウンサンプリング)が '距離' とともに増すにつれて、ひどい結果を生みます。中央の画像は最初の画像と同じですが、歪んだ出力画像を10倍に拡大してから(グリッドリサンプリング)他の画像に合わせてスケールバックしたものです。すなわち、各宛先ピクセルにつき100以上のピクセルが参照され平均化され、結果を スーパーサンプリング しました。生成はかなり高速で(1.2秒)、画像全体の品質を改善しますが、その改善は限定的です。上の例で使った ×10 は非常に重く、ほとんどのスーパーサンプリング用途で使われるより典型的な3倍や4倍のスケーリングをはるかに超えています。結果の最大の違いは、スーパーサンプリングが画像全体にわたって一様に全般的な品質改善を行うだけだということです。歪みがより激しくなるにつれ、破綻し始めます。その結果が、中景にはっきり見える リサンプリングアーティファクト であり、より具体的には地平線のすぐ手前にある一連のひどいモアレ効果です。モアレ効果は、ピクセルあたり10サンプルが画像のチェッカーボードパターンとほぼ一致するときに生じ、歪んだ色効果を生み出します。一方、エリアリサンプリングは、前景のピクセルよりも地平線に近い問題のあるピクセルに(ほぼすべての時間を費やして)より集中します。前景のピクセルでは、実際にスーパーサンプリングを上回ります。基本的に上の例は非常に極端な歪みであり、EWA 参照にかかる時間もそれに見合っています。より一般的には、単一の補間参照よりはるかに良い結果を生み出します。関与するすべてのピクセルを効率的に見つつ、スーパーサンプリングのように、必要のない領域でサンプルを使いすぎないからです。まとめ… 単純な楕円(EWA リサンプリング)や矩形(Resize)を使って 'エリアリサンプリング' を行うことは、良い結果を生み出します。なぜなら、スケール、アフィン、透視歪みに関与するすべてのソースピクセルが統合され、個々の宛先ピクセルの最終的な色を生成するからです。DePolar 歪み のような非常に非線形な歪みや、Shepard's 歪み やレイトレーシングのような不確定な歪みの場合、必要なすべてのソースピクセルをリサンプリングするための正しい '領域' を見つけることは法外なものになり、スーパーサンプリングが結果を改善する最良の手法になります。しかし、まっすぐなタイリング、拡大、スケーリングなしの回転には、非常に高速な単一の 'point' 補間参照だけでおそらく必要十分で、完全な no-op(変化なし)歪みを保証するためにはむしろ推奨されることもあります(後述)。ただし、すべてのリサンプリング技法は、個々のピクセルの色を決定する手法にすぎないことを覚えておいてください。それは実際には、宛先とソース(あるいは可能なら逆)の間の位置のマッピングに関する点を除き、画像をどう歪ませるかの一部ではありません。


一般化歪みオペレータ

これらの例の生成、IM フォーラム での議論、そして透視や他の歪みをより簡単かつ高速に行う方法を求めるユーザーからの多数の要望を受けて、さまざまな種類の画像歪みをより簡単に追加できるよう、IM v6.3.5-1 に新しいオペレータが追加されました。この 一般化歪みオペレータ は "[-distort](https://imagemagick.org/command-line-options/#distort)" と呼ばれ、お使いの IM バージョンで利用可能な歪み手法は "[-list](https://imagemagick.org/command-line-options/#list) Distort" で確認できます。

  magick -list distort

"[-distort](https://imagemagick.org/command-line-options/#distort)" オペレータは二つの引数を取ります。一つは上記で与えられる歪み 手法 のうちの一つ、もう一つは特定の歪み手法を制御するために使われる、カンマまたは空白で区切られた浮動小数点値のリストからなる第二の文字列引数です。

  magick ... -distort  {_手法_}  "{_浮動小数点値のリスト_}" ...

ただし、与える浮動小数点値の数は使う歪み手法に大きく依存し、その意味も選んだ 手法 だけでなく、特定の手法に必要な制御点や属性の正確な数にも依存することがあります。これは特に '[Scale-Rotate-Translate](#srt)'(略して '[SRT](#srt)')歪みに当てはまります。これは実際には三つの別々の '[Affine](#affine)' 歪みを一つの歪みにまとめたものです。多くの歪み 手法 は(画像座標 での)制御点のリストを取り、通常これらは画像をどう変形させるかを制御する 座標のペア として与えられます。これらの座標ペアについては、後の 制御点を使った歪み でより詳しく説明します。

歪みのオプション、制御、設定

Best Fit +Distort フラグ

デフォルトでは "[-distort](https://imagemagick.org/command-line-options/#distort)" は通常、ソース画像を元画像と同じサイズの画像へ歪ませます。これには例外があり、たとえば '[Arc](#arc)' 歪み(極座標マッピングの一種)では、入力ソース画像のサイズは歪んだ形の画像においてあまり意味を持ちません(詳細は下の Arc 歪み を参照)。オペレータのもう一つの形式 "[+distort](https://imagemagick.org/command-line-options/#distort)"(IM v6.3.5-7 で追加)は、古い 回転およびシアー オペレータが行うのと同様に、歪んだ画像のサイズを変えて入力画像全体を(可能なら)含むようにしようとします。ただし、この特定の '動作モード' はさらに進んで、結果画像の 仮想キャンバスオフセット(page) も設定します。こうすることで、後で適切な アルファ合成 を使って、制御点に従った正しい位置でこの画像を別の画像に レイヤーマージ できます(基本例として アフィンレイヤリングによる3D立方体 を参照)。また(歪み手法によっては)、"[+distort](https://imagemagick.org/command-line-options/#distort)" はソース画像に存在しうる既存の 仮想キャンバスオフセット を考慮に入れ、歪みのプロセスの一部として使おうとします。個々の歪み手法に関する注記を参照してください。そのため、'best-fit' な "[+distort](https://imagemagick.org/command-line-options/#distort)" 形式の一般歪みオペレータを使う に、そのオフセットをクリアまたは調整するために "[+repage](https://imagemagick.org/command-line-options/#repage)" 属性設定オペレータを慎重に使う必要があるかもしれません。また、仮想キャンバスとオフセットが不要なら、 にも使う必要があるかもしれません。キャンバス/page ジオメトリの削除 も参照してください。通常の "[-distort](https://imagemagick.org/command-line-options/#distort)" は、歪みそのものに関してはソース画像に存在する既存のオフセットを単に無視しますが、そのオフセットを変更せずに歪んだ画像へコピーします。まとめると… 結果を同じサイズの画像へマッピングするには "[-distort](https://imagemagick.org/command-line-options/#distort)" を使います。出力画像サイズを自動設定しようとし、なおかつ仮想キャンバスオフセット(page 属性)を使用・生成するには "[+distort](https://imagemagick.org/command-line-options/#distort)" を使います。この全般的なビューポート選択を上書きし、歪んだ画像のどのサイズのどの部分を結果で見たいかを正確に制御したい場合は、歪みビューポート(後述)も参照してください。
注意… "[+distort](https://imagemagick.org/command-line-options/#distort)" が生成する best-fit ビューポートは、ユーザーが通常予想するより2ピクセル大きくなります。その理由は、これらのピクセルがエリアリサンプリングフィルタから生じる半透明ピクセルを含み、これらのピクセルが正しい '縁の接合' と歪んだ画像の重ね合わせに不可欠だからです。技術的には、追加されるピクセル数は出力スケーリングの リサンプリングフィルタサポート に依存すべきです。すなわち、リサンプリングフィルタによってピクセルの領域がどれだけ '広がる' かに依存します。しかし各ピクセルのスケーリングは可変であるため、絶対的に正しい追加ピクセル数の計算は非常に厄介な問題で、たいてい労力に見合いません。したがって2ピクセルの追加は 'ごまかし' です。歪みが画像を拡大してピクセルをより '広げる' ことはめったにないからです。また、ほとんどの標準的なリサンプリングフィルタのサポートが2単位なので、2ピクセルの追加は妥当なものです。さらにこの追加は '固定' なので、ユーザーは望むなら(さまざまな方法で)単純に 画像サイズを切り抜く という選択肢を持てます。2ピクセルの 'ごまかし' は、画像の拡大を行うときには明らかに小さすぎになります。しかしそれはかなりまれな歪みであり、これが問題ならユーザーは自分で ビューポート(後述)を定義できます。仮想キャンバス上の歪んだ画像の仮想オフセットは、これら2つの追加ピクセルを考慮して調整されるので、歪んだ画像は重ね合わせには正しいものの、単純な合成には正しくありません。ただし注意が必要なのは、CropTrim はレイヤー化された画像位置を保持しますが、ShaveChop は、このオフセットに対してレイヤー画像をずらしてしまうことです。

歪みのピクセル色決定

上記の 逆ピクセルマッピング で説明したように、結果画像の各点は、選んだ歪み手法に従って、まず宛先画像でのそのピクセル位置をソース画像内の等価な(逆歪みした)位置へマッピングすることで決定されます。しかしピクセルの最終的な色を決めるのはそれほど単純ではありません。なぜなら、それは多数の要因に影響されるからです。

仮想ピクセルとタイリング

歪みでマッピングされた点が、実際のソース画像にヒットせず、そのすぐ脇や、あるいは実際の画像からかなり離れた場所になることがあります。この解決策は、ソース画像が '無限' または '仮想' の面に囲まれていると見なすことで、これは現在の "[-virtual-pixel](https://imagemagick.org/command-line-options/#virtual-pixel)" 設定によって定義されます。この設定の効果の詳細と例については、仮想ピクセル の例を参照してください。これは、ソース画像の歪んだ、あるいは歪んでいないタイルパターンを生成するのに非常に有用です。この技法は、仮想ピクセル セクション自体(歪みなし)と、下の アフィンタイリング および 遠い地平線を眺める で示されています。

無効な歪みピクセル

宛先ピクセルの歪みが、仮想タイル画像にすら 'ヒット' しないことがあります。これは通常、何らかの3次元空間歪み手法を使って画像を歪ませ、ピクセルの 'ベクトル' が画像のあるソース平面にすらヒットしないときに起こります。基本的に歪みの結果が数学的に '未定義' になるのです。その場合、色は "[-mattecolor](https://imagemagick.org/command-line-options/#mattecolor)" 設定から決定されます。たとえば 透視歪み で '空' が見える場合(たとえば 遠い地平線を眺める を参照)、ソース画像の位置を決定する数学が '未定義' になりました(実際には定義されているのですが、ユーザーの順方向視点からは有効ではありません)。そのため、'空' には "[-mattecolor](https://imagemagick.org/command-line-options/#mattecolor)" が出力されます。実際、透視歪みアルゴリズムは地平線に近いピクセルのために何らかの 'アンチエイリアス' 情報を含めることにも成功していますが、そうした状況では珍しいことです。

EWA リサンプリングとフィルタ

宛先ピクセルがソース画像のどこに 'ヒット' するかがわかったら、ソース画像内のその 'ヒット' 点の近くのピクセルを使って、宛先ピクセルにする色を決定する必要があります。通常 歪みオペレータ は、エリアリサンプリング 手法 EWA(楕円加重平均)を使って、ソース画像のより大きな領域を平均し、このピクセルの正しい色を割り出します。EWA リサンプリングで使うフィルタは、"[-filter](https://imagemagick.org/command-line-options/#resize)" 設定で変更できます。詳細は リサンプリングフィルタ、より具体的には 円筒フィルタ を参照してください。当初、EWA リサンプリングには 円筒ガウシアン フィルタが使われていました。これは EWA リサンプリングの元の研究論文で定義されたものだったからです。しかしこれは非常にぼやけた結果を生み出す傾向がありました。ただし、エイリアシング効果は生じません。これは、そのバージョンより前には極端なぼけを引き起こす実装バグ(現在は修正済み)とともに、デフォルトのフィルタでした。IM v6.6.5-0 以降、Laurentian 大学の数学教授 Nicolas Robidoux との大きな議論を経て、画像歪みのデフォルトフィルタは、EWA リサンプリング向けに特別に設計された、非常に 'Mitchell 風' の3次フィルタである '**Robidoux**' フィルタに置き換えられました。このフィルタや他の円筒フィルタの情報については、円筒フィルタ を参照してください。ただし、基礎となる窓付き Sinc フィルタ関数は、より円形の窓付き Jinc フィルタ関数に置き換えられることに注意してください。そのため、'Lanczos' フィルタを選ぶと、"Sinc 窓付き Sinc" フィルタではなく "Jinc 窓付き Jinc" フィルタが返されます。詳細は 窓付き Jinc 円筒フィルタ を参照してください。余談: 'Sinc' 関数は、円筒関数としては実際には使えません。なぜなら、その関数とグリッド上の放射状距離との相互作用により、偶数個の 'ローブ' が使われるときには必ず、フィルタの重みが自身を打ち消し合う(重みの合計がゼロになる)形になるからです。これが今度は、ピクセルレベルのチェッカーボード 'ハッシュ' パターンで使われると、ほぼ無限の色を生成しようとする原因になります。基本的に EWA は、Resize オペレータ とほぼ同様にリサンプリングフィルタを使うので、特別な エキスパートフィルタオプション を使ってフィルタを変更することもできます。たとえば 'Gaussian' やガウシアン風フィルタのぼけは、フィルタブラー設定 で制御できます。同様に、ローブサポート設定 を使って、'Lanczos' フィルタのような窓付き Jinc フィルタのサイズと強さを制御できます。 | _EWA リサンプリングを自動的にオフにし、より直接的な 補間参照 のみを使う極端な歪み手法がいくつかあります。

たとえば Depolar 歪みは、'楕円'(EWA)リサンプリングにあまり適合しない円弧の形のリサンプリング領域を生成します。Shepards のような他の歪みは、'スケーリング係数' の計算を極めて困難にします(ただし将来の歪みオペレータの改善でこれを可能にできるかもしれません)。

これらの歪み手法では、結果の画像圧縮(ダウンサンプリング)の領域で深刻な エイリアシングアーティファクト が生成されるのを防ぐため、スーパーサンプリング 技法が推奨されます。

_
---|---

リサンプリングの失敗

特殊な状況では、EWA リサンプリングの楕円が、加重平均を作るための実際のピクセルに一つも 'ヒット' しないことがあります。基本的に楕円が非常に小さいか細いため、画像のすべてのピクセルの間に完全に落ちてしまうのです。ピクセルの色がなければ、その点で出力画像の色を生成できません。これは極端な状況で、エキスパートフィルタ設定 で遊んでいるのでない限り、一般に達成不可能です。しかし、万一どのピクセルにもヒットしない場合や、フィルタの重みの合計がゼロになる場合、リサンプリングは失敗します。その場合 IM は、EWA フィルタリングをオフにしたときに得られるのと同じように、単純な直接補間参照にフォールバックします(次を参照)。これが起きているか確認したい場合は、('red' のような)珍しい背景色とともに特別な 背景補間 を使い、そのようなリサンプリングの失敗を強調できます。たとえばここでは、ボックスフィルタのサポートを意図的に小さくしすぎて、リサンプリング楕円を非常に小さくします。また、どの部分が 'ピクセルにヒット' し、どの部分がしなかったかを見られるよう、画像を大きく拡大します。 |

  magick \( xc:red   xc:white xc:black +append \) \
          \( xc:blue  xc:lime  xc:white +append \) \
          \( xc:black xc:red   xc:blue  +append \) -append \
          -filter Box -define filter:support=0.4 \
          +distort SRT 30,0  bad_box_distort.png

[IM Output]
大きく拡大したこの画像では、リサンプリング円が一つのピクセルだけにヒットする(単色のエイリアス化した円を生成する)か、円形サンプリング領域がピクセルの間に完全に落ちてしまってどのピクセルにもマッチせず、そのためフィルタが補間された色のグラデーション(デフォルトでは バイリニア補間)にフォールバックして、少なくとも結果画像に何らかの妥当な色を得ます。ここでは同じ例ですが、補間手法を特別な(そして通常は役に立たない)背景補間('gray' に設定された背景色を返すだけ)に置き換えています。 |

  magick \( xc:red   xc:white xc:black +append \) \
          \( xc:blue  xc:lime  xc:white +append \) \
          \( xc:black xc:red   xc:blue  +append \) -append \
          -filter Box -define filter:support=0.4 \
          -interpolate background -background Gray \
          +distort SRT 30,0   bad_box_distort_gray.png

[IM Output]
完全なカバレッジ(常に少なくとも一つのピクセルを見つけるため)を得るには、円筒リサンプリングフィルタには少なくとも約 0.707(sqrt(2)/2)の 'サポート'(ボックスフィルタのデフォルト)が必要です。すべてのフィルタは通常、この最小サポートサイズよりはるかに大きいものです。この例については、円筒フィルタ のセクションを参照してください。 | _角にある小さな色付きの点は、仮想ピクセルのリサンプリング最適化(単色の VP 領域をサンプリングする際に高価な EWA リサンプリングを中断する)によって生じます。これらは "[-virtual-pixel](https://imagemagick.org/command-line-options/#virtual-pixel)" 設定を変えると消えたり変わったりします。

通常これは問題にならず、ここで見えるのは、distort が元画像よりわずかに大きい 'best-fit ビューポート' を使い、そのため縁の周りに余分なピクセルが数個含まれ、この場合それが仮想ピクセルをサンプリングしているからにすぎません。

_
---|---

補間または直接の色参照

"[-filter](https://imagemagick.org/command-line-options/#filter) point" を使うと、フィルタリング、ひいては EWA リサンプリングをオフにできます。 これを行うと、ImageMagick は色参照を、高速で単純な ピクセル補間 に切り替えます。すなわち、'リサンプリング領域' なしで、ソース画像への '単一点' の参照だけを使って色を調べます。結果ピクセルの色は、点に最も近い近傍だけに基づく補間された色を使います。

補間は、画像の縮小やダウンサンプリングが何らかの形で起こるとき、
一般に深刻なエイリアシング効果を引き起こします。

しかし、回転、タイリング、あるいは 画像の拡大(拡大やアップサンプリング)のような、最小限の歪みを含む画像では、極めてうまく機能します。スーパーサンプリング 技法を補間と組み合わせて、強い圧縮・縮小・ダウンサンプリングの領域で結果を改善できます。補間によるエイリアシングを解決するためにスーパーサンプリングを使う例については、Depolar-Polar サイクルの問題(EWA リサンプリングを使えない歪み)を参照してください。

詳細な歪みの概要

"[-distort](https://imagemagick.org/command-line-options/#distort)" を実行する前に "[-verbose](https://imagemagick.org/command-line-options/#verbose)" を設定すると(再びオフにするには "[+verbose](https://imagemagick.org/command-line-options/#verbose)" を使用)、distort は、指定された方法で与えられた画像を歪ませる際に計算し使用するアルゴリズムや内部係数に関する情報を、標準エラーチャネルに出力します。この情報を使って、歪みがどう働き適用されるかを見て理解できます。これはまた、何がうまくいっていないかを把握するためのデバッグツールであり、新しい歪みの実装プロセスの一部でもあります。

  magick koala.gif -verbose -distort SRT 0 +verbose  koala_noop.gif

[IM Output] | | | [IM Text]

| [IM Output]

| 注意: 結果画像は入力画像とほとんど、しかし厳密には同じではありません(次の "no-op 歪み" を参照)。
---|---
詳細出力は、与えられた歪みに対する二つの代替歪み技法の詳細を示します。一つは '[AffineProjection](#affineprojection)' 歪みで、もう一つは DIY FX オペレータ の代替で、出力画像のピクセル (i,j) を入力画像の補間参照 (xx,yy) へどうマッピングして画像を変換するかを正確に詳述します。それはリサンプリング楕円の計算を行い、複雑な数学(固有値)を使って割り出しますが、ここで詳細出力されるのは、(i,j) ピクセルの色を決定するための、ソース画像内のスケーリングされていない補間参照点だけです。どちらも歪みのプロセスに関する情報を提供し、同じ種類の他の歪みで使う追加情報を抽出するのに使えます。この情報を使うより複雑な例については、下の 透視の内部バイリニアの内部 を参照してください。また、画像歪みに FX コマンドを使う例については、FX 画像リサイズ を参照してください。上記の余分な '0.5' の加算と減算は、'ピクセル座標' を '画像座標' に変換するために必要で、画像歪みの正しい数学的処理に必要です。下の 画像座標対ピクセル座標 を参照してください。

No-Op 歪み

上の例は、no-op 歪みを行った結果を示しています。すなわち、(何らかの副次的効果のために)画像を distort に通すものの、実際の歪みは一切伴わない(ピクセルの1対1マッピングだけ)ものです。EWA リサンプリングフィルタは元画像とまったく同じ色を再現せず、個々のピクセルをその近傍とごくわずかにぼかします。これは使われる2次元フィルタによるもので、色のぼけは最小限ですが、決して除去できません。そのため、真の 'no-op' を行うには、EWA フィルタリングもオフにして 補間または直接の色参照(上記)を使う必要があります。 |

  magick koala.gif -filter point -distort SRT 0  koala_noop_perfect.gif

[IM Output]
ほぼすべての 補間設定 は、正確に参照されたとき、一般にソースピクセルの正確なコピーを取り出します。ただし念のため、最近傍 補間を指定して、distort が生成するかもしれない浮動小数点誤差にかかわらず、正確な色一致のみが返されるよう、速度と確実性を得ることもできます。 |

  magick koala.gif   -filter point  -interpolate nearest \
          -distort SRT 0  koala_noop_perfect_2.gif

[IM Output]
これは逆効果に思えるかもしれませんが、元の画像データを実際にリサイズせずに、画像の領域を拡大したり、画像をタイリングしたり(仮想ピクセル手法 を使用)するのに非常に有用な方法になります。この例については Distort を介した仮想ピクセルによるタイリング を参照してください。すなわち、歪みオペレータ を、複数画像の仮想ピクセルタイリング、画像サイズの拡大や切り抜き、境界の追加、さらには(整数あるいはサブピクセル量での)平行移動といった副次的効果のために使うのです。これらはいずれも、実際には画像を '歪ませる' 必要はなく、何らかの 'プログラムされた' 方法で '修正' するだけです。

ビューポート、Distort が見る場所

上述のとおり、"[-distort](https://imagemagick.org/command-line-options/#distort)" または "[+distort](https://imagemagick.org/command-line-options/#distort)" を使うと、結果の '宛先画像' のサイズと位置がそれぞれ、ソース画像と同じ(仮想キャンバス設定を無視)か、歪んだソース画像の best-fit 計算(可能な場合)のいずれかに変わります。これら二つは基本的に、結果の '歪んだ空間' のどの部分を宛先画像が見るかを定義します。別の考え方をすれば、宛先画像は結果の歪んだ画像を見る '窓'、すなわち歪んだ空間への 'ビューポート' です。"distort:viewport" 設定はこれら両方のデフォルトを上書きし、歪んだ空間のどの部分を見たいかを直接指定できます…

[-define](https://imagemagick.org/command-line-options/#define) distort:viewport=WxH+X+Y
[-set](https://imagemagick.org/command-line-options/#set) option:distort:viewport WxH+X+Y

これらは IM v6.3.6-1 で追加されました。これは歪んだ画像を拡大したりスケーリングしたりはせず、歪んだ画像空間内で見られる位置と領域(ビューポート)を指定するだけです。これは、特定サイズの宛先画像を作ったり、歪んだ画像空間内の特定領域へ視点をずらしたりするのに使えます。これは、無限サイズの(仮想ピクセルで定義された)歪んだ画像の 'ビューポート切り抜き' を使うのと非常によく似ています。たとえばここでは、出力をコアラの頭だけに(no-op 歪みで)切り抜きます。言い換えれば、歪んでいない元画像の単なる直接 'ビューポート切り抜き' です。 |

  magick koala.gif  -define distort:viewport=44x44+15+0 \
          -filter point -distort SRT 0  +repage koala_viewport.gif

[IM Output]
そしてここでは視点を広げて、歪んだ画像を取り囲む余分な空間を見て、仮想ピクセル 設定が元のソース画像を取り囲む無限空間に及ぼす効果を示します。 |

  magick koala.gif  -define distort:viewport=125x125-25-25 \
          -filter point -distort SRT 0  +repage koala_viewport_2.gif

[IM Output]
この場合、画像を拡大するために Extent オペレータ を使うのに近いものです。ただし単に背景色で埋めるのではなく、distort は追加された領域を 仮想ピクセル設定 で埋めます。この場合、デフォルトの '[Edge](misc.html#edge)' 仮想ピクセル設定を使っており、元画像の縁に沿ったピクセルから複製された、水平・垂直のピクセル線になります。仮想ピクセル設定 にはもっと良い選択をするとよいでしょう。たとえば '[Background](misc.html#background)' 設定を使うと、この no-op 歪みは Extent オペレータ とほぼまったく同じように働きます。この画像では '[White](misc.html#white)' 仮想ピクセル設定がおそらくより良い選択でしょう。 |

  magick koala.gif  -define distort:viewport=125x125-25-25 \
          -virtual-pixel White -distort SRT 0  +repage koala_viewport_3.gif

[IM Output]
前の例の最後の "[+repage](https://imagemagick.org/command-line-options/#repage)" は、ビューポート設定が使われたときに "[-distort](https://imagemagick.org/command-line-options/#distort)" が残すビューポートの仮想キャンバスオフセットを除去するために必要です。この情報はこの場合は不要です。他の場合、たとえば歪んだ画像をレイヤー化するときには、そのオフセット情報が欲しくなるでしょう。ビューポートオプションは '[Tile](misc.html#tile)' や '[Mirror](misc.html#mirror)' 仮想ピクセル設定で特に有用で、任意のサイズで異なるスタイルのタイル状画像を生成できます。下の アフィンタイリング で例示されるように、distort を使ってそれらのタイル状画像を歪ませることすらできます。 |

  magick koala.gif  -define distort:viewport=125x125-25-25 \
          -virtual-pixel Mirror -distort SRT 0  +repage koala_viewport_4.gif

[IM Output]

中央の正方形切り抜き

"[-set](https://imagemagick.org/command-line-options/#set)" オプションを使って結果画像の 'ビューポート' を設定する場合、割り当てる値に パーセントエスケープ を含められます。より具体的には、数学的計算ができる FX パーセントエスケープ を含められます。これは、'ビューポート' を計算でき、その際にメモリ内の現在の画像のサイズなどの属性を利用して、結果画像の最終サイズを指定できることを意味します。どういうことでしょうか。つまり、'ビューポート' を使って、通常は画像の一度以上の事前読み込み(あるいはより高度な API プログラミングインターフェース)と外部計算を必要とする、特殊な種類の 切り抜き を生成できるのです。たとえば、元画像のサイズや向きを事前に知らなくても、画像の '中央の正方形' を切り抜けます。これは複雑なので、読みやすく、コードしやすく、デバッグしやすいように、ビューポート式を変数に入れました。とはいえ実際にはただの定数(固定)式です。

  size='%[fx: w>h ? h : w ]'
  offset_x='%[fx: w>h ? (w-h)/2 : 0 ]'
  offset_y='%[fx: w>h ? 0 : (h-w)/2 ]'
  viewport="${size}x${size}+${offset_x}+${offset_y}"

  magick worldmap_sm.jpg  -set option:distort:viewport "$viewport" \
          -filter point -distort SRT 0  +repage   viewport_square.gif

[IM Output] [IM Output]

結果画像は、どんな入力ソース画像からでも、その画像のサイズにかかわらず抽出できる、最大の中央正方形になります。この歪み自体は実際には画像を歪ませず、ビューポートが覆う領域をコピーするだけです。'中央の正方形切り抜き' を生成するには、4つの数値すべてを計算する必要があることに注意してください。すべての値は画像の向きに依存するからです。そのため各式は 'w>h ? ... : ...' という形の '画像の向き' テストを使い、結果の値が画像の向きに依存するようになっています。これは画像の向きテストの代わりに "min()" と "max()" 関数を使った別の形式です。 |

  magick worldmap_sm.jpg  -set option:distort:viewport \
    "%[fx:min(w,h)]x%[fx:min(w,h)]+%[fx:max((w-h)/2,0)]+%[fx:max((h-w)/2,0)]" \
    -filter point -distort SRT 0  +repage  viewport_square_2.gif

[IM Output]
Fred Weinhaus の Tidbits ページ のご厚意による。同じことを複数の画像処理技法を使って行う手法は、サムネイル、正方形のパディングと切り抜き に示されています。

アスペクト比切り抜き

この技法は、与えられたアスペクト比に合うよう画像を中央切り抜きできるように拡張できます。フォーラムの議論 アスペクト比への切り抜き も参照してください。

その他のビューポートの例

歪んだ空間のどの部分を結果で見えるようにするかをビューポートで制御する他の例については、下の 画像を回転する手法 も参照してください。

出力スケーリングとスーパーサンプリング

[-define](https://imagemagick.org/command-line-options/#define) distort:scale=N
[-set](https://imagemagick.org/command-line-options/#set) option:distort:scale N

これは IM v6.4.2-6 で、一般的な出力画像スケーリング係数として追加されました。これは出力画像を与えられた係数で拡大し、そのため "[-distort](https://imagemagick.org/command-line-options/#distort)" は N2 倍多くの歪み参照 'サンプル' を生成する必要があります。この数値は通常整数ですが、浮動小数点の拡大係数にもできます。多くの歪みでは結果の歪んだ画像の 'スケール' サイズも指定できますが、結果の画像サイズはそのスケーリングの影響を受けません('best-fit' の "[+distort](https://imagemagick.org/command-line-options/#distort)" が使われた場合を除く)。ただし、この 'scale' 設定は結果画像の内容を一切変えず、結果の出力画像を拡大または縮小するだけです。これはたとえば、適切な 'ビューポート' と組み合わせて、特定サイズに容易に "[-resize](https://imagemagick.org/command-line-options/#resize)" できる画像を生成し、品質を損なわずに歪んだ画像への制御された 'ズーム' を生成するのに使えます。たとえば、コアラの頭に 'ズーム' インします。 |

  magick koala.gif -set option:distort:scale 2.5 \
          -set option:distort:viewport 44x44+15+0 \
          -distort SRT 0  +repage koala_zoom.gif

[IM Output]
ビューポートは 44x44 ピクセルを要求しましたが、実際の出力画像は 110x110 ピクセルにスケーリングされていることに注意してください。より一般的には、これは歪み演算を単純に 'スーパーサンプリング'(上記)する手段として使われます。このために整数の 'スーパーサンプリング' スケール係数が使われ、画像を歪ませた後、元のサイズにスケールバックして余分なサンプルを統合し、より高品質な結果を生成します。 |

  magick koala.gif -filter point -set option:distort:scale 10 \
          -distort SRT 0  -scale 10%   koala_super.gif

[IM Output]
また、画像品質を改善するために 'スーパーサンプリング' を使う場合、'エリアリサンプリング' は不要なので(速度を落とすだけ)、通常は "[-filter](https://imagemagick.org/command-line-options/#filter) point" オプションを使ってオフにします(前のセクションを参照)。


歪み手法の紹介

Scale-Rotate-Translate(SRT)歪み

最も単純な歪みの一つでありながら、おそらく最も汎用的なものの一つが、'SRT' または 'Scale-Rotate-Translate' 歪みです(SRT は単なる手早い略記)。この歪みの 'no-op' の例は上の例ですでに見ました。そこでは画像に実際の歪みを一切適用せずに処理されましたが、それでもフィルタリングはされ、ごくわずかなぼけが生じることがあります。ここで上の 'no-op' 歪みの結果を繰り返します…

  magick koala.gif    -distort SRT 0    koala_noop.gif

[IM Output] [IM Output]

| _エリアリサンプリング を使う結果として、画像はごくわずかにぼけることに注意してください。ただし IM のリサンプリングフィルタは、No-Op 歪みでのこのぼけを最小限に抑えるよう意図的に設計されており、これは通常の使用に必要なものです。

特別な目的で完璧な 'no-op' 歪みが欲しい場合は、EWA リサンプリングをオフにします。すなわち、distort オペレータの前に 'no-op' フィルタ "-filter Point" を上記に指定します。


---|---
'SRT' 歪みは実際には、一つの歪み手法の中に三つの別々の歪みがあり、そのため 'Scale-Rotate-Translate' 歪みと呼ばれます。_angle
回転を除くすべての引数はオプションで、このため引数は、カンマまたは空白で区切られた引数を正確にいくつ与えるかに応じて、最大7つの浮動小数点数まで非常に可変的になります。 **-distort SRT "** |

                  Angle

| **"** | -> 中心回転
---|---|---|---

        Scale     Angle

| -> 中心での拡大縮小と回転

X,Y               Angle

| -> 与えられた座標を中心に回転

X,Y     Scale     Angle

| -> 座標を中心に拡大縮小して回転

X,Y ScaleX,ScaleY Angle

| -> 同上

X,Y     Scale     Angle  NewX,NewY

| -> 座標を拡大縮小・回転・平行移動

X,Y ScaleX,ScaleY Angle  NewX,NewY

| -> 同上
これが行うのは、選択した画像とオプションの制御点を取ることです。制御点が与えられない場合、入力ソース画像の正確な中心が使われます。その点を中心に、歪みは順に次のことを行います。画像を 拡大縮小 し、回転 し、それから選択した制御点を新しい位置へ 平行移動 つまり動かします。これがこの歪みの名前の由来です。上に示した引数の順序は、実際に画像に適用される演算の順序を反映しています。X,Y で変換の '中心' を原点へ平行移動し、画像を ScaleX,ScaleY で拡大縮小し、Angle で画像を回転し、それから '中心' を NewX,NewY のこれらの座標へ平行移動します。すなわち、このオペレータは実際には4つの内部歪み演算を表しており、それらすべてが一つの歪みとして同時に適用されます。ただし私たち人間にとっては、3つの異なる歪みだけが関与しているように見えます。では 'koala' 画像を使った単純な例を見てみましょう… 引数を1つにすると、単に画像の中心を軸とした単純な回転になり、基本的には古い Rotate オペレータ と同様の結果を生み出しますが、画像サイズの増加はありません。 |

  magick koala.gif  -background skyblue  -virtual-pixel background \
          -distort ScaleRotateTranslate -110 koala_srt_rotate.png

[IM Output]
デフォルトでは入力画像のサイズが出力画像にも使われるため、回転した画像はクリップされることがあります。また、画像のピクセル数が奇数か偶数かにかかわらず、完璧に中央に配置されます。'プラス' 形式の "+distort" を使い、結果の仮想キャンバスオフセットをクリーンアップすると、通常の Rotate オペレータ に非常によく似たものを生成できます。 |

  magick koala.gif  -background skyblue  -virtual-pixel background \
          +distort ScaleRotateTranslate -110 +repage koala_srt_rotate2.png

[IM Output]
| IM 6.7.3-4 以降、Rotate オペレータ は Distort SRT 歪みを使うようになりました。これより前は シアー演算 を使っており、それほど良い結果を生み出しませんでした。
---|---
30% 縮小もしてみましょう。ただし透明な背景を使います。 |

  magick koala.gif  -alpha set -virtual-pixel transparent \
          +distort ScaleRotateTranslate '.7,-110' +repage koala_srt_scale.png

[IM Output]
次の引数のセットは、画像が回転・拡大縮小される '中心' を指定します。この点は画像の '制御点' または 'ハンドル' と呼ばれ、歪みを制御するために使われる位置です。この歪みには特定の点を使うので、'仮想オフセット' の複雑さを避けるために 'best-fit' モードは使わないことにします。たとえばコアラを 'はな'(ソース画像の 28,24 にあります)を中心に回転・拡大縮小してみましょう。ついでに X と Y のスケールを別々に歪ませてみます。 |

  magick koala.gif  -background skyblue -virtual-pixel background \
          -distort ScaleRotateTranslate '28,24  .4,.8  -110' \
          koala_srt_center.png

[IM Output]
そして最後の例として、'はな' を画像の下端近くへ動かし、背景を合わせて白い背景に設定してみましょう。 |

  magick koala.gif  -virtual-pixel white \
          -distort ScaleRotateTranslate '28,24  .4,.8  -110  37.5,60' \
          koala_srt_trans.png

[IM Output]
最終位置も浮動小数点値であることに注意してください。実際、すべての引数は浮動小数点値にでき、歪みは正しく処理します。各演算、Scale、Rotate、Translate は、その順序で実行されることを覚えておいてください。ご覧のとおり、この歪みは非常に汎用的で、画像を3つの異なる手法で順番に歪ませると考えることもできますが、実際には3つすべての歪みを同時に適用して、示された結果を生み出しています。これにより、複数の個別オペレータを実行するより高速になり、一般により良い最終結果を生み出します。上記はまた、実際のソース画像の外側を参照する領域に使われる色を定義する、異なる 仮想ピクセル 設定の使用も示しています。回転に対する 補間 の効果を見るには、回転した線と縁の補間 を参照してください。この歪みは特に、画像を取り、その物体の動きや回転に基づくアニメーションを生成するために設計されています。たとえばここでは、様式化された宇宙船を作り、それを非常に粗い方法でアニメーション化します。宇宙船は(最初の 'しゃがみ込み' のスケーリングのために)その基部 20,75 に座っており、一方、移動と回転の通常の 'ハンドル' は、元画像の 20,60 にある宇宙船の中心です。これらの点は、物体を単純に簡単な言葉でアニメーション化できる制御点を表します。

  magick -size 80x80 xc:skyblue -fill yellow -stroke black \
          -draw 'path "M 15,75 20,45 25,75 Z  M 10,55 30,55" ' \
          spaceship.gif
  magick spaceship.gif \
          \( -clone 0  -distort SRT '20,75  1.0,0.6  0' \) \
          \( -clone 0  -distort SRT '20,60     1     0  20,49' \) \
          \( -clone 0  -distort SRT '20,60    0.9   20  27,35' \) \
          \( -clone 0  -distort SRT '20,60    0.8   45  40,23' \) \
          \( -clone 0  -distort SRT '20,60    0.5   70  55,15' \) \
          \( -clone 0  -distort SRT '20,60    0.3   75  72,11' \) \
          \( -clone 0  -distort SRT '20,60    0.1   80  100,8' \) \
          -set delay 50  -loop 0  spaceship_launch.gif

[IM Output] [IM Output]

もちろん、これは '[SRT](#srt)' 歪みを使って静止画をアニメーション化する方法の非常に粗い例ですが、考え方はわかるでしょう。フレームを増やしたり、炎や煙を加えたりして、さらに改善できます(投稿を歓迎します。最良の結果はあなたの名前とともにここに追加されます)。

画像を回転する手法

画像はさまざまな方法で回転できます。しかし、単純な回転では求めているものにならないかもしれません。サイズを変えずに画像を回転… |

  magick rose: -virtual-pixel black -distort SRT '20'  rotate_normal.png

[IM Output]
あるいは、回転した画像をクリップしないように回転… |

  magick rose: -virtual-pixel black +distort SRT '20'  rotate_noclip.png

[IM Output]
しかし通常は、画像本体を取り囲む 'black' の 仮想ピクセル(あるいは他の非画像色)を見たくないでしょう。一つの解決策は、回転の結果として実際の画像ピクセルだけを含む、同じアスペクト比の最大の矩形へ画像を(歪みビューポート設定 を使って)切り抜くことです。しかしこの矩形を計算するのはかなり厄介で、Math Help Forum で見つけたいくつかの方程式を使って ImageMagick フォーラム で盛んに議論されました。ここでは回転し、できるだけ元のアスペクト比に近い内部切り抜きを行います。 |

  angle=20
  ratio=`magick rose: -format \
     "%[fx:aa=$angle*pi/180; min(w,h)/(w*abs(sin(aa))+h*abs(cos(aa)))]" \
     info:`
  crop="%[fx:floor(w*$ratio)]x%[fx:floor(h*$ratio)]"
  crop="$crop+%[fx:ceil((w-w*$ratio)/2)]+%[fx:ceil((h-h*$ratio)/2)]"
  magick rose: -set option:distort:viewport "$crop" \
          +distort SRT $angle +repage   rotate_internal.png

[IM Output]
これは複雑に見えますが、それは ビューポート設定 を定義するために、幅、高さ、そして元画像内のオフセットという4つの別々の値を実際に計算しなければならないからです。もう一つの代替案は、回転するだけでなく、元画像の範囲を '埋める' ように画像をわずかに大きくスケーリングすることです。 |

  angle=20
  magick rose: -distort SRT \
     "%[fx:aa=$angle*pi/180;(w*abs(sin(aa))+h*abs(cos(aa)))/min(w,h)], $angle" \
     rotate_correction.png

[IM Output]
この最後の方法は、画像の元のサイズを保つので、写真のわずかな回転補正 に理想的です。この方法がより単純なのは、計算する必要のある 'スケール' 値が1つだけで、そのため 'インライン' で行えるからにすぎません。

制御点を使った歪み

'[SRT](#srt)' 歪み手法は回転角度とスケーリング係数を指定することで定義されますが、ほとんどの歪みは、ソース画像上の '点' を動かし、それらを結果画像の新しい位置へ動かすことで定義されます。これは、'[SRT](#srt)' 平行移動を定義するときの '中心' 点の動きに少し似ています。これらの点は制御点と呼ばれ、より一般的には、単一の制御点ごとに4つの浮動小数点値(座標の2ペア)を与えることで定義されます。そのため歪みはしばしば、4つの値の複数のセットによって定義されます。たとえば…

X1,Y1 I1,J1 X2,Y2 I2,J2 X3,Y3 I3,J3 X4,Y4 I4,J4 . . . .

ここで、ソース画像内の制御点 Xi,Xi(その仮想キャンバスに相対)は、歪んだ宛先画像の Ii,Ji へマッピングされます。 ただし 歪みオペレータ は実際には宛先座標をソース座標へマッピングしている(逆ピクセルマッピング を参照)ので、上記の内部的な使い方は、I,J 座標を X,Y 座標へマッピングすることです。しかし結果は同じはずで、ただ考え方が異なるだけです。
歪みオペレータ が最初に導入された IM バージョン 6.3.6-0 より前は、制御点の座標の順序は、すべてのソース座標に続いてすべての宛先座標、と定義されていました。しかしこれは、どのソース座標と宛先座標が互いに対応するかを判断するのを非常に難しくし、また歪みをさらに精細化するために制御点を単純に追加することもできませんでした。
--- ---
これがこのように定義されているのは、各個別制御点の動きが、カンマ(または空白)で区切られた浮動小数点値のリストの中でまとまって保たれるようにするためです。これはまた、将来の外部 '制御点ファイル' の使用も可能にします。制御点を使う最も単純な歪みは '[Affine](#affine)' 歪みです。ただし後で見るように、これは通常3つの点で定義されますが、1つまたは2つの制御点の動きだけを使うこともできます。実のところ '[SRT](#srt)' は単に '[Affine](#affine)' 歪みの2点または1点のサブセットです。たとえばここでは、コアラ画像の 'はな' '28,24' を新しい位置 '45,40'(赤い矢印で示す)へ動かし、その結果、画像位置の単純な '平行移動' になります。
  magick koala.gif  -virtual-pixel white \
          -distort Affine '28,24 45,40'   koala_one_point.png

[IM Output] [IM Output]

2つの点があれば、'[Affine](#affine)' 歪みは画像を平行移動できるだけでなく、拡大縮小や回転もできます('[SRT](#srt)' 歪みの全範囲)。たとえばここでは、コアラの '耳'('30,11' と '48,29' からの赤い線)を、より大きな水平位置('15,15' から '60,15' への青い線)へマッピングし、制御点がこの新しい位置へ動くように画像を拡大縮小・回転・平行移動する必要があります。

  magick koala.gif  -virtual-pixel white \
          -distort Affine '30,11 15,15  48,29 60,15'   koala_two_point.png

もちろん '[SRT](#srt)' 歪みでも上記の2点 '[Affine](#affine)' 歪みを再現できたはずですが、ここでは歪みを異なる方法で定義しただけです。どちらの形式を使うべきかはあなた次第で、何を達成しようとしているかによります。

画像座標対ピクセル座標

一般的な場合の制御点の使用は簡単ですが、歪んだ画像を別の画像や描画された構造物と整列させる必要があるときには、より難しくなります。その理由は、IM のほとんどのオペレータは座標を 'ピクセル位置'(たとえば 切り抜き描画 などのとき)で扱うのに対し、歪みは座標を数学的な '画像座標' で扱うからです。覚えておくべきなのは、画像内のピクセルは '点' ではなく、実際には1ピクセル単位のサイズの '領域' だということです。すなわち、10,10 にあるピクセルは、10 単位下/横から 11 単位下/横までの正方形の色の領域を定義します。画像座標 の観点では、'ピクセル' の中心は実際には 10.5,10.5 にあります。すなわち、画像を歪ませて 'ピクセル' の中心を特定の位置へ動かすときには、0.5 を加える必要があります。そのため、画像の角の 'ピクセル' を再配置するには、0.5,0,5_Width_ -0.5,_Height_ -0.5 にあるピクセルの観点で画像を動かす必要があります。一方、画像の実際の '縁' の観点で画像を再配置するには、単に座標 0.0,0,0_Width_ ,_Height_ を使います。何を実際に配置したいのか、画像の 'ピクセル' の中心なのか、画像の '縁' なのか、を考える必要があるだけです。あるいは、それが自分の特定の問題で実際に重要かどうかを。歪んだ画像に他の要素を 描画 したい場合は、描画位置を 'ピクセル位置' の観点で与える必要があることを覚えておいてください。そして、そうです、"-draw" オペレータは浮動小数点値を使って線、円、その他の形状を描画できます。同様に、物体のストローク幅や半径も浮動小数点値で与えられます。 [IM Output] [IM Output]

| _1.0 未満の描画ストローク幅はうまく機能しません(線の描画 を参照)。また、領域の塗りつぶしは塗りつぶし領域の縁に余分な 0.5(ストローク幅の追加に合わせて)を加えます(Draw 塗りつぶし境界 を参照)。これは実際に使われるストローク幅にかかわらず行われます。

詳細は Draw 塗りつぶし境界 を参照してください。私はこれをバグと見なしています。_

パーセントエスケープを使った制御点

歪み引数の中で パーセントエスケープ を使うこともできます。たとえば、ある画像の画像属性を抽出し、それを使って別の画像をその最初の画像に合わせてリサイズできます。ここでは "rose:" 組み込み画像のサイズを取得し、それから '[Affine](#affine)' 歪みを使って、より大きな "logo:" 画像を同じサイズへリサイズします(アスペクト比は保持しません)。 |

   magick rose: -set option:rw %w -set option:rh %h +delete \
           logo: -alpha set -virtual-pixel transparent \
           +distort Affine '0,0 0,0     %w,0 %[rw],0   0,%h  0,%[rh]' \
           +repage logo_sized_as_rose.png

[IM Output]
distort は仮想キャンバス上にわずかに大きな 'レイヤー画像'(負のオフセットを含む)を生成するので、上の例で "[+repage](https://imagemagick.org/command-line-options/#repage)" を含める必要があったことに注意してください。また縁もぼやけます。distort は画像の正確な、つまり真の歪みを生成しており、整然と直交化された リサイズ画像 ではないからです。Resize オペレータ が行うのとまったく同じように 歪みオペレータ を使って画像をリサイズするより高度な例については、Distort 対 Resize と、下の Distort Resize 手法 を参照してください。また、現在の画像リスト内の画像位置に基づいて歪みを計算するのにパーセントエスケープを使うこともできます。この例は アニメーション化された歪み に示されています。

制御点の最小二乗フィット

'[Affine](#affine)' 歪みに3つより多くの制御点を、あるいは '[Perspective](#perspective)' または '[Bilinear](#bilinear)' 歪みに4つより多くの点を与えると、ImageMagick はそれらの歪みの '平均' 的な表現を見つけるために、与えられたすべての点にわたって最小二乗平均を行います。これは、ある画像を別の画像と合わせようとしている('画像レジストレーション' として知られる技法)場合、必要な最小数より多くの点を定義して、結果がより精密な歪みになるようにできることを意味します。もちろん、それらの点の一つ以上が他の点とうまく '適合' しない場合、IM は悪い点を含むすべての制御点を使って最良の適合を見つけようとするので、結果は 'おかしな' 点によって歪みます。状況によっては '悪い座標ペア' を見つけて除去する何らかのチェックが必要になるかもしれません。

ファイルからの制御点

歪みへの数値(引数)のリストは、"[-annotate](https://imagemagick.org/command-line-options/#annotate)" や "[label:](text.html#label)" のようなものにテキストを入力できるのと同じように、'@filename' 構文を使ってファイルから読み込むこともできます(テキスト引数のエスケープ文字 を参照)。たとえば、このように歪みを指定できます…

  magick input.png  -distort Perspective '@file_of_coords.txt' output.png

ファイル名を単に '@-' にすると、標準入力からファイルを読み込むことを意味します。ファイル自体は文字列として読み込まれ、関与する歪みが必要とする座標(引数)のリストとして扱われます。数値はカンマまたは空白で区切れるので、座標ペアを1行に1ペアの座標という形できれいに並べられます…

   X1   Y1   I1   J1
   X2   Y2   I2   J2
   X3   Y3   I3   J3
   X4   Y4   I4   J4
   ....

それが 最小二乗フィット と組み合わさり、画像レジストレーションの使用を非常に実用的にします。ファイルは1行あたり4つの数値のリストにすぎないので、"cut"、"paste"、"column" などの他のテキスト処理スクリプトツールや、"sed"、"awk"、"perl" などのより高度なテキスト処理スクリプトツールを使って座標を操作できます。座標と歪み引数ファイルの使用は、'[Shepards](#shepards)' 歪みや、数百の座標ペアが関与しうる将来予定されている 'Grid' および "Mesh' 歪みのような、より高度な歪みでより重要になります。


アフィン(3点)歪み手法

アフィン歪み

上で示した '[SRT](#srt)' 歪みと、'Affine' 歪みの1点・2点形式はいずれも、実際には完全な3点形式の 'Affine' 歪みの単純化です。実際、任意の '[SRT](#srt)' 歪みの "-verbose" 出力を調べると(例については verbose 歪み設定 を参照)、内部的には本当に '[AffineProjection](#affine_projection)' 歪み(後述)であることがわかります。上記の手法が完全には扱えなかった唯一の歪み効果は、Shear オペレータ が提供するような 'シアー' でした。それには3点アフィン歪みを使う必要があります。これは、最初の座標マッピングを '原点' とし、他の2つの座標マッピングをその原点からのベクトルと想像することで、3点歪みと考えられます。たとえばここでは、テキストを描画し、そのテキストに相対する3つの制御点を定義するために赤と青の 'ベクトル' を重ねます。今、それら2本の線の(画像座標 としての)座標を動かすことで、それらの線の新しい位置に合うように、そのテキスト画像を平行移動・回転・拡大縮小・シアーできます。

  magick -background lightblue -fill Gray -font Candice \
      -size 100x100 -gravity center label:Affine\! \
      -draw 'fill blue stroke blue path "M 3,60 32,60 M 27,58 27,62 32,60 Z"' \
      -draw 'fill red  stroke red  path "M 3,60  3,30 M  1,35  5,35  3,30 Z"' \
      label_axis.png
  magick label_axis.png \
          -distort Affine ' 3.5,60.5   3.5,60.5
                           32.5,60.5  32.5,60.5
                            3.5,30.5  33.5,20.5' label_axis_distort_shear.png
  magick label_axis.png \
          -distort Affine ' 3.5,60.5   3.5,60.5
                           32.5,60.5  27.5,85.5
                            3.5,30.5  27.5,35.5' label_axis_distort_rotate.png
  magick label_axis.png \
          -distort Affine ' 3.5,60.5  30.5,50.5
                           32.5,60.5  60.5,80.5
                            3.5,30.5  30.5,5.5' label_axis_distort_affine.png

[IM Output] [IM Output] [IM Output] [IM Output]

最初の例では3番目の座標(垂直な赤い線の)だけが変更され、画像がシアーされて Y 軸方向に引き伸ばされました。もちろん Y 軸だけに限られるわけではありません。後の例では、回転や平行移動を含む、画像へのより大胆な変更を行っています。もちろん Annotate Text オペレータも、同じようにして実際のテキストをスキューできますが、角度の変更だけです。そのオペレータはテキストを特定の方向に拡大したり大きくしたりはしません。すなわち、'ベクトル' を回転できても、それを長くしたり短くしたりすることはできません。例の表については Annotate 引数の使用 を参照してください。アフィン歪みは、描画されたテキストだけでなく、どんな画像に対してもこの種の歪みを行えます。3つより少ない、または多い座標ペアを使うアフィン 制御点ペアが1つまたは2つだけ与えられた場合、IM はそれらのより少ない点の動きに合うように、より限定された形式のアフィン歪みを使います。たとえば座標ペアが1つだけの場合、画像のスケーリングなしの平行移動に限定されます。2つの点では、'[Scale-Rotate-Translation](#srt)' 歪み(シアーなし)に限定されます。例については前の 制御点を使った歪み の議論を参照してください。'[Affine](#affine)' 歪みに3つより多くの制御点が与えられた場合、IM は 最小二乗フィット を使って、与えられた すべて の座標ペアに合う最良の '3点' アフィン歪みを見つけます。これは、ソース画像の制御点が宛先画像の制御点に正確にマッピングされないかもしれず、与えられたすべての点の best-fit な '平均' になることを意味します。たとえば文書のスキャンがある場合、文書の4つの角すべてを見つけてマッピングし、アフィン歪みで文書の回転と拡大縮小を補正できます。こうすれば、3点ではなく4点に基づいて、より良い '平均' 適合を得られます。座標が多いほど、より良いより正確な歪みを生成できますが、一つの座標ペアが非常に悪い場合、最小二乗フィットはまったく良い適合を生成しないかもしれないことに注意してください。'悪い座標ペア' を除去する何らかのチェックが必要になるかもしれません。将来: 各入力座標ペアが他と相対してどれだけ '正確' かを報告するコードを IM に追加し、ユーザーがどの '悪い点' を除去すべきかを判断する助けにする。

アフィン射影(Affine Projection)歪み

すでに述べたように、'[SRT](#srt)' 歪みのさまざまな引数と '[Affine](#affine)' 歪みの制御点は、'Affine Projection' の '係数' を表す6つの特別な数値に数学的に変換されます。アフィン射影のこれらの数値は、ソース画像の点を宛先画像へ 順方向マッピング するために使われる係数です。すなわち、ソース画像 x,y を宛先画像 i,j へマッピングするために使われる数学的な値です。6つの浮動小数点引数は(与える順序で)…

sx, rx, ry, sy, tx, ty

これらが今度は歪み式を形成します… Xd = | sx*Xs + ry*Ys + tx | , | Yd = | rx*Xs + sy*Ys + ty |
---|---|---|---|---|---
ここで "Xs,Ys" はソース画像座標、"Xd,Yd" は宛先画像座標です。内部的には、ImageMagick Distort は上記の方程式を逆にして、適切な ピクセルマッピング を行い、"Xd,Yd" 座標をソース画像の "Xs,Ys" の色参照へマッピングします。さまざまなアフィン射影マトリックスの値が画像にどう影響するかの詳細については、アフィンマトリックス変換 サブページを参照してください。これらの係数をすでに事前計算している(distort の 詳細出力 から抽出したか、あるいは他の形式の入力引数から他の手法を使って自分で計算した)場合、それらを IM に直接与えて画像を歪ませられます。たとえばここでは、制御点の動きではなく、角度を使って係数を計算して画像を 'シアー' します。 |

   angle=-20
   tan=`magick xc: -format "%[fx:tan( $angle *pi/180)]" info:`
   magick koala.gif -alpha set -virtual-pixel Transparent \
           +distort AffineProjection "1,$tan,0,1,0,0" +repage \
           koala_affine_proj.png

[IM Output]
ImageMagick でこの歪みを行う古い方法は、"-affine" と "-transform" のオペレータ対を使うことでした。しかし IM v6.4.2-8 以降、これは 歪みオペレータ の 'プラス' または 'bestfit' 形式を使った 'AffineProjection' への単純な呼び出しにすぎません。詳細は アフィンマトリックス変換 サブページを参照してください。

アフィン歪みの例

アフィンタイリング

これまで見てきた上記3つのアフィン風歪み手法はすべて、歪んだ画像に基づくさまざまなタイルパターンを生成する興味深い方法も提供します。

  magick checks.png    -alpha set    -virtual-pixel tile \
          -distort  ScaleRotateTranslate  '20,20  .5  30' \
          checks_srt_tile.png
  magick checks.png    -alpha set    -virtual-pixel tile \
          -distort  Affine  '0,0 10,10   0,89 10,50   89,0 50,0' \
          checks_affine_tile.png
  magick checks.png    -alpha set    -virtual-pixel tile \
          -distort  AffineProjection  '0.9,0.3,-0.2,0.7,20,15' \
          checks_amatrix_tile.png

[IM Output] [IM Output] [IM Output] [IM Output]

このように歪みマッピングを使うことは、実際には3Dグラフィックライブラリやゲームで 'テクスチャマッピング' が機能する方法そのものです。唯一の違いは、それらが面の3次元座標を2次元画像へ戻してマッピングすることです。'no-op' 歪み("-distort SRT 0")でさえ、適切な 歪みビューポート を使えば、アニメーション化されたグリッタータイル のような画像のシーケンス全体をタイリングする有用な方法を提供します。

  magick glitter_blue.gif -virtual-pixel tile \
          -filter point -set option:distort:viewport 100x100 -distort SRT 0 \
          glitter_blue_tiled.gif

[IM Output] [IM Output]

ここでも "[-filter](https://imagemagick.org/command-line-options/#filter) point" を使って EWA リサンプリング をオフにし、演算を高速化するとともに、ソース画像ピクセルの完璧な(サンプリングされていない)コピーを保証していることに注意してください。歪みビューポート はオフセットも指定でき、結果画像でタイル状画像を 'ロール' できます。

アフィンレイヤリングによる3D立方体

'[Affine](#affine)' 歪みは、その制御点とともに、3つの画像から正投影立方体や等角投影立方体(定義については Wikipedia の 正投影等角投影 を参照)を生成するのに理想的です。必要なのは、宛先画像上の4つの制御点を割り出すことだけです。画像レイヤリング技法 を使うので、点は負の値を持つことすらでき、IM が生成されたワープ画像に応じて最終画像サイズを調整できます。この例では、立方体の中心に制御点 '0,0' を、そしてその中心点の周りに等間隔に '-87,-50'、'87,-50'、'0,100' の3点を選びます。あとは、3つの(できれば正方形の)画像の適切な角をこれらの制御点へマッピングするだけです。 |

  magick \
     \( lena_orig.png -alpha set -virtual-pixel transparent \
        +distort Affine '0,512 0,0   0,0 -87,-50  512,512 87,-50' \) \
     \( mandrill_orig.png -alpha set -virtual-pixel transparent \
        +distort Affine '512,0 0,0   0,0 -87,-50  512,512 0,100' \) \
     \( pagoda_sm.jpg -alpha set -virtual-pixel transparent \
        +distort Affine '  0,0 0,0   0,320 0,100    320,0 87,-50' \) \
     \
     -background none -compose plus -layers merge +repage \
     -bordercolor black -compose over -border 5x2     isometric_cube.png

[IM Output]
画像を歪ませる際に、画像の実際の縁の 座標 を使ったことに注意してください。これは数学的には、画像がぴったり合うはずだということを意味します。また、画像を単に(デフォルトの Over アルファ合成 を使って)'合成' しなかったことにも注意してください。それをすると、画像の間にわずかに透明な '隙間' ができます。正しい方法(示したとおり)は、'縁で接する' 部品をつなぐために Plus アルファ合成 を使うことで、透明な隙間のない完璧な接合になります。詳細は マスクされた2つの画像の整列 を参照してください。その後、余分な境界を加え、すべての透明度を除去しました。これは必須ではなく、簡単にどんな背景(または "none")も使えますが、そうすると画像に隙間があった場合にそれが目立ちます。
[IM Output] 右に示すのは、画像内のそうした接合の一つの拡大で、接合に沿って 'black で埋められた' 隙間がないことを示しています。"-distort" を使わずに等角投影立方体を作る別の方法は、シアーを使った等角投影立方体 に示されています。ただしこの技法では、サブピクセル座標を使えず(上の例では使っていませんが、使うこともできました)、画像をピクセル単位(整数)座標で配置することに制限されます。

アフィンシアーによる3D影

上で使ったのと同じレイヤリング手法は、奇妙な形のかっこいい3次元の影を生成するのにも使えます。直立している任意の '平らな' 形の影を加えます。たとえば、直立できるように平らな基部を持つ形を作りましょう。 |

  magick -background None -virtual-pixel Transparent -fill DodgerBlue \
          -pointsize 72 -font Ravie  label:A   -trim +repage \
          -gravity South -chop 0x5  standing_shape.png

[IM Output]
この '形' は、画像の最後の行でもある平らな基部を持っていることに注意してください。これは重要です。なぜなら、影が直立する形にその行に沿って接続するよう、その行に沿って形を歪ませるからです。この '直立する形' から3D影を生成するコマンドは次のとおりです。 |

  magick standing_shape.png   -flip +distort SRT '0,0 1,-1 0' \
          \( +clone -background Black -shadow 60x5+0+0 \
             -virtual-pixel Transparent \
             +distort Affine '0,0 0,0  100,0 100,0  0,100 100,50' \
          \) +swap -background white -layers merge \
          -fuzz 2% -trim +repage   standing_shadow.jpg

[IM Output]
上記は、示された結果を達成するためにかなり多くのステップを行っています。しかし最も厄介なのは最初の行です。これは画像を反転し、それから '歪み反転' で再び戻します。この結果、最下行は仮想キャンバス上で Y=0 の値を持つように配置されます。すなわち、画像全体に負のオフセットが与えられ、最下行が仮想キャンバスの原点を通るように配置されます。この 'トリック' を行うことで、抽出した '影' に非常に単純な 'アフィンシアー' を使って歪ませられます。そのため、影を歪ませるのに形画像のサイズを知る必要はなく、それでもすべてを '揃え' たまま保てます。すべてが元画像の最下(Y=0)行に沿って同期したままだからです。影が落ちる方向とその長さは、単に 'アフィンシアー' の最終座標('100,50')を調整するだけで調整できます。最初の2つの '座標ペア' は変更すべきではありません。これらは最下行に沿って影を元画像に 'ロック' するからです。ただし、最後のステップまでずっと、すべての画像は負の仮想キャンバスオフセットを含むので、中間処理画像を表示または保存する予定がある場合は注意が必要です。この影効果の唯一の問題は、それが '一様なぼかし' であることです。すなわち、影が写実的でないのです。実際には、影は '直立する形' に接合するところで鋭く、影が遠ざかるにつれてよりぼやけるべきです。しかしこれは、距離ぼかし影フォント で使われるような 可変ぼかしマッピング を使って行えます。

透視圧縮による3D影

これは影に可変ぼかしを加える別の方法です。実際には推奨しませんが、実装はかなり簡単です。この例は 可変ぼかしマッピング が ImageMagick に追加される前に開発されました。基本的には、まず最初の影の形を 透視歪み(下で詳しく見ます)を使って歪ませ、影の '遠い部分' を大きく圧縮してぼかし、それからその圧縮を、上で使った最終的な 'アフィンシアー' 位置へ歪ませることで拡張します。 |

  magick standing_shape.png   -flip +distort SRT '0,0 1,-1 0' \
          \( +clone   -virtual-pixel Transparent -mattecolor None \
             +distort Perspective \
                '0,0 0,0  100,0 100,0   0,-100 45,-100   100,-100 60,-100' \
             -fuzz 2% -trim   -background Black -shadow 60x3+0+0 \
             +distort Perspective \
                '0,0 0,0  100,0 100,0   45,-100 -100,-50   60,-100 0,-50' \
          \) +swap -background white -layers merge \
          -fuzz 2% -trim +repage     standing_shadow_var.jpg

[IM Output]
これは元の 3D 影の例 とほぼまったく同じですが、いくつか余分なステップがあります。元の形はまず台形に歪まされ、それから次のステップを高速化するために余分な空間がトリミングされます。それから歪んだ形からぼかした影を抽出します。歪んだ画像から影画像が作られたら、同じ制御点を使って影画像を歪み解除し、アフィンシアーとしての位置へ動かします。鍵は、影のぼかしが歪んだ画像に対して起こり、それが歪み解除される(この場合は同時にアフィンシアーもされる)ことです。その結果、ぼかしも歪まされ拡張されて、影の上部の周りでよりぼかし、基線に沿ってはるかに少なくぼかします。透視ぼかしの結果として、地面の基線から約100ピクセル離れたところでピークになるはずの可変ぼかしが得られます。これは最初の透視ぼかし制御点で定義されています。

Distort を使って画像をリサイズ

DistortResize は、実際には多くの面で非常によく似ています。どちらも画像歪みオペレータで、どちらも 逆ピクセルマッピング を使って結果画像を作ります。どちらも色の決定のために "[-filter](https://imagemagick.org/command-line-options/#resize)" 設定とそのエキスパート制御を利用しますが、その方法は大きく異なります。Resize は単純化された(そしてはるかに一般的な)画像歪み演算で、多くの最適化を可能にします。それは直交整列されており、リサイズで2パスの直交画像フィルタリング手法を使えます。すなわち、中間の一時画像を使って、まず一方の次元でサイズを変え、それから他方の次元でサイズを変えます。また、スケーリング係数が宛先画像全体で一定で、縁が整数ピクセル次元に整列されているため、アルゴリズムは処理と、使うフィルタのキャッシュ要件を大幅に単純化できます。これらすべての制限により、distort が行う必要のある作業に比べて非常に高速になる、さまざまな最適化が可能になります。Distort も 画像をリサイズ できますが、元画像から結果の新しい画像へ直接変換する1パスで行います。縁を整数ピクセル位置に整列させる必要はなく、各ピクセル位置を回転・拡大縮小できます。言い換えれば、最終結果の各ピクセルに対して多くの余分な処理を行う必要があり、最適化の余地がより少ない、はるかに一般的なオペレータです。DistortResize と等価な画像を生成させるには、まったく同じ制限に従い、複雑な画像処理のトリックを使う必要があります。これは IM フォーラムの 正しいリサイズ(distort を使用) で議論され、アフィン歪み手法 の使用に基づく等価な distort リサイズ技法が生まれました。この結果としての 'Resize' 歪み手法は ImageMagick バージョン 6.6.9-2 で追加されました。この歪みのコマンドラインインターフェース(CLI)版は、Resize が受け取るのとまったく同じ ジオメトリ引数 を受け取り、2つの次元のスケーリング係数のわずかな差異も含めて、これを直接のリサイズ代替にします。 |

  magick logo:  -distort Resize 150x  logo_resized.png

[IM Output]
| _'Resize' 歪み手法への他の API インターフェースは、引数として2つの数値だけを受け取り、それらは結果画像の最終的な整数サイズとして扱われます。現時点では、最終画像サイズを変更するさまざまなリサイズ制御フラグを持つ実際のジオメトリ引数は受け取りません。すなわち、パーセンテージ、拡大/縮小のみ、あるいはアスペクト比の保持といったフラグは利用できません。

この特別な画像歪み手法へのそうしたサポートを追加するのは、それらの API の保守者に任されています。_
---|---
上記の Distort Resize と通常の Resize オペレータ の本当の違いは、distort 版が、あらゆるピクセルの最終的な色を決定するために、はるかに遅い1パスの 円筒(楕円)フィルタ を使うことです。言い換えれば、2パスの直交フィルタ(resize)と、1パスだが2次元の円筒フィルタ(distort resize)の直接の比較を提供します。そうした比較の一例については Distort 対 Resize を参照してください。

Distort Resize の内部

以下は、上記の Distort Resize が内部的に行った等価な演算です。

  magick logo:  -alpha set -virtual-pixel transparent \
          +distort Affine '0,0 0,0   %w,0 150,0   0,%h 0,113' \
          -alpha off  -crop 150x113+0+0 +repage   distort_resize.png

値 '150' と '113'(2か所で使用)は、最も近い整数への最終画像の希望サイズです。これは、最終的な整数サイズの制限を保ちつつ、画像のアスペクト比をできるだけ良く保とうとして計算されました。これらは通常、与えられたリサイズ ジオメトリ引数 から、別の API 関数を使って ImageMagick が計算します。それから透明度と透明な 仮想ピクセル を有効にして、外部の '仮想ピクセル' が最終ピクセル色の計算に関与しないようにします。歪みが完了すると、透明度は再び除去(オフに)され、distort が加えた 'バッファ' ピクセルが 画像切り抜き を使って除去されます。透明ピクセルを使うため、上記のコマンドは、上で例示した "logo:" 組み込み画像のような、透明度を含まない画像でのみ正しく機能します。これはより複雑な版で、画像に存在しうる透明度から 仮想ピクセル の効果を分離するために必要です。

  magick logo: -alpha set -virtual-pixel transparent \
          \( +clone -alpha extract -alpha opaque \) \
          +distort Affine '0,0 0,0   %w,0 150,0   0,%h 0,113' \
          -alpha off -crop 150x113+0+0 +repage \
          -compose CopyOpacity -composite      distort_resize_trans.png

これは2つの歪みを行います。まず画像を歪ませ、それからアルファ(透明度)チャンネルを別々に歪ませます。それぞれの場合で、仮想ピクセルの効果を除去するために transparent を使います。その結果、元画像に透明度がない場合のものより少なくとも2倍遅くなります。これら両方の技法は、Distort Resize 手法 によって内部的に実装されています。そのため、この '手法' は実際にはユーザーのための便利な 'マクロ' であり、実際の本物の歪み手法ではなく、'アフィン' 歪みです。


4点歪み手法

透視歪み

おそらく最もよく要求される種類の歪みは、高速な透視歪み演算です。これは4点歪みなので、少なくとも4セットの制御点ペア、つまり16の浮動小数点値が必要です。たとえばここには建物の画像があります。この画像から、4つの点(赤)の位置を手動で発見しました。また、建物の正面を 'まっすぐにする' あるいは '正す' ために、それらの点を最終画像で変換する最終位置(青)も定義しました。

  magick building.jpg \
          -draw 'fill none stroke red polygon 7,40 4,124, 85,122, 85,2' \
          building_before.jpg
  magick building.jpg \
          -draw 'fill none stroke blue polygon 4,30 4,123, 100,123, 100,30' \
          building_after.jpg

[IM Output] [IM Output] [IM Output]

実際の画像歪みを行うには、それらの座標を "-distort" の 'perspective' 手法に与えるだけです。

  magick building.jpg -alpha set -virtual-pixel transparent \
         -distort Perspective \
              '7,40 4,30   4,124 4,123   85,122 100,123   85,2 100,30' \
          building_pers.png

[IM Output] [IM Output]

右上の空白領域に注目してください。そこでは歪みがソース画像のピクセルデータを '外し' ました。この状況で IM が行うことは、"-virtual-pixel" 設定によって制御されます(仮想ピクセル を参照)。あまり気づきにくいのは、元画像の最左端のわずかな部分も同じ理由で '失われ' ていることです。参考までに、各マッピングペアの座標を入れ替えて、歪みを逆にもしてみましょう。これにより、画像が歪みによってどれだけ劣化したかがわかります。

  magick building_pers.png  -alpha set -virtual-pixel transparent \
         -distort Perspective \
              '4,30 7,40   4,123 4,124   100,123 85,122   100,30 85,2' \
          building_pers_rev.png

[IM Output] [IM Output] [IM Output]

悪くありません。多くの 'ぼやけ' が存在しますが、それは仕方ありません。'ぼやけ' が、最も圧縮された画像の右側でより悪いことに注目してください。すべての歪みはこの圧縮問題に悩まされるので、すでに歪んだ画像を歪ませるのではなく、常に元画像から歪ませるようにすべきです。これはこの変換を使った別の例で、上で作った特別なチェッカーボードテスト画像を使い、歪ませてから歪みを逆にします。

  magick checks.png        -alpha set    -virtual-pixel transparent \
          -distort Perspective '0,0,0,0  0,90,0,90  90,0,90,25  90,90,90,65' \
          checks_pers.png
  magick checks_pers.png   -alpha set    -virtual-pixel transparent \
          -distort Perspective '0,0,0,0  0,90,0,90  90,25,90,0  90,65,90,90' \
          checks_pers_rev.png

[IM Output] [IM Output] [IM Output]

画像圧縮によって生じたわずかなぼやけが見えますが、画像は基本的に復元されています。実際に起こっているのは、IM が与えられたすべての制御点ペアを使って、'[Perspective Projection](#perspectiveprojection)'(次を参照)の適切な係数を計算することです。Verbose 設定を含めると、係数と、IM がこの歪みを実行するために内部的に使っている DIY FX 等価式 の両方を見られます。3つ以下の制御点ペアしか与えられない場合、IM はより単純な '[Affine](#affine)' 歪みに自動的にフォールバックします。一方、('画像レジストレーション' のための)4つより多くの点は、与えられたすべての制御点に最も適合する歪みを見つけるために 最小二乗フィット されます。将来: 代替案。4つの座標は三角形と中心点を表すこともできます。三角形を固定して中心点を動かすか、あるいはその中心を固定して他の3つの座標を動かして、透視ビューを生成できます。 歪みがどう機能するかをより詳しく見たい場合は、下の 透視の内部 を見てください。また、PDF 論文 透視整正Gernot Hoffmann による)で提示された Postscript 実装も見られます。Leptonica アフィンおよび透視変換 も見てみてください。

遠い地平線を眺める

画像の境界内に '消失点' を生成するように座標を調整すると、透視歪み を使って非常に珍しい効果を生み出せます。 |

  magick checks.png -mattecolor DodgerBlue \
          -virtual-pixel background -background Green \
          -distort Perspective '0,0 20,60  90,0 70,63  0,90 5,83  90,90 85,88' \
          checks_horizon.png

[IM Output]
さて、元画像を '取り囲む' 仮想ピクセルには 'Green' を使い、これは 仮想ピクセル背景設定 を使って有効にしました。しかしより興味深いのは、"[-mattecolor](https://imagemagick.org/command-line-options/#mattecolor)" 設定を使って定義された 'blue' 色の出現です。この 'blue' 色は、歪みによって生成されたピクセルが 無効 である領域を表し、そうした領域では "-distort" オペレータは単に "[-mattecolor](https://imagemagick.org/command-line-options/#mattecolor)" 設定を出力します。透視歪み では、結果画像の '空' に行き着くピクセルはすべて無効と分類されます。また、'空' を、ソース画像が現れない '地平線' の側として定義します。'空' は、結果画像が歪みによって大きく短縮された場合にのみ、透視歪み画像に現れます。最終画像の結果に '空' が欲しくない場合、最良の方法は "[-background](https://imagemagick.org/command-line-options/#background)" と "[-mattecolor](https://imagemagick.org/command-line-options/#mattecolor)" の両方を同じ色を使うように設定することです。透視歪み は、特別な無限タイリング 仮想ピクセル 設定の一つが使われたとき、より興味深くなります。たとえばここでは '[tile](misc.html#tile)' 設定を使って無限タイル状の平面を生成しました。 |

  magick checks.png  -virtual-pixel tile -mattecolor DodgerBlue \
          -distort Perspective '0,0 20,60  90,0 70,63  0,90 5,83  90,90 85,88' \
          horizon_tile.png

[IM Output]
この画像について一つ警告を。無限タイル状画像を要求すると、生成が 非常に遅く なります。画像が大きいほど遅くなります。"[-monitor](https://imagemagick.org/command-line-options/#monitor)" 動作制御設定 を使って "[-distort](https://imagemagick.org/command-line-options/#distort)"(や他の遅い画像処理タスク)の進行を監視できます。基本的に、地平線に近い単一ピクセルについて、ImageMagick は適切な色を割り出すために元画像から膨大な数のピクセルを平均する必要があります。これには非常に長い時間がかかることがあります。ImageMagick は、情報をキャッシュしたり、さまざまな 仮想ピクセル 設定の組み込み知識を使ったりして、これらの地平線近くのピクセルの処理に使う時間を制限しようとしますが、それでも長い時間がかかることがあります。この手法の詳細については、上の エリアリサンプリング を参照してください。別の無限タイル状の透視画像は、ランダム仮想ピクセル設定 を使って生成できます… |

  magick checks.png  -virtual-pixel random -mattecolor DodgerBlue \
          -distort Perspective '0,0 20,60  90,0 70,63  0,90 5,83  90,90 85,88' \
          horizon_random.png

[IM Output]
起こっているのは、画像を取り囲むすべての仮想ピクセルが、画像自体の中の任意のピクセルをランダムに選んだものだということです。その結果、画像の地平線に向かって見るにつれて、より滑らかでよりぼやけていくランダムノイズからなる地面になります。特定の繰り返しパターンなしに、自然な奥行きの感覚を与えます。ここでは上記を繰り返しますが、純粋な白黒のソース画像を使いました。しかし私が興味があるのは実際の歪んだ画像ではなく、生成された 仮想ピクセル 'random' パターンだけなので、特別な '-set option:distort:viewport' 設定を使って、'歪んだ画像空間' のどの部分を見るかを変えました。この設定は、見られる歪んだ空間の領域の通常のサイズと位置を上書きします。この場合、歪んだ画像ではなく、仮想ピクセルだけを含む領域です。 |

  magick -size 90x90 pattern:gray50 -alpha set \
       -virtual-pixel random -mattecolor none \
       -set option:distort:viewport 120x120+100-15 \
       -distort Perspective '0,0 20,60  90,0 70,63  0,90 5,83  90,90 85,88' \
       +repage -size 120x50 gradient:dodgerblue-tomato \
       -compose DstOver -composite    sunset_horizon.png

[IM Output]
画像を完成させるために、("[+repage](https://imagemagick.org/command-line-options/#repage)" を使って)ビューポートオフセットを除去し、夕焼け色のグラデーションを透明な '空'("[alpha setmattecolor](https://imagemagick.org/command-line-options/#mattecolor)" で設定)に 下敷きまたは DstOver しました。他の画像処理作業の背景として使えそうな、非常に興味深い画像です。歪みパラメータを調整して、地平線の高さと傾きを調整できます。ここにタイル状透視歪みのより伝統的なテストがあります。 |

  magick pattern:checkerboard -scale 120x120 -normalize \
          -virtual-pixel tile  -distort Perspective \
             '0,0 10,61   119,0 60,60   0,119 5,114   119,119 125,110' \
          checkered_plain.gif

[IM Output]
私の研究では、上のテストは誤解を招くものだとわかりました。なぜなら、画像のほぼ等倍のスケール(遠い領域ではなく前景の領域)でのエリアリサンプリング技法の品質について、実際の指標を与えないからです。すなわち、リサンプリングアーティファクト で説明したようなリサンプリングの問題をよく見ることです。この最後の画像はまた、地平線に近い '打ち切り' 点を示しています。そこでは ImageMagick が、(現在の仮想ピクセル設定を考慮して)ピクセルの適切な色を割り出そうとする価値はないと判断し、EWA アルゴリズムを短絡して画像全体の平均色を使いました。これがこの画像で見えるのは、画像に存在する大規模な対角線の色パターンのためだけです。画像の平均色は、歪み演算ごとに一度だけ、最初に必要になったときにのみ計算されます。それを使うことで、ImageMagick は地平線近くの色の計算に膨大な時間を節約します。通常その結果は画像の平均色になるからです。これは、楕円が浮動小数点の限界を超えるほど引き伸ばされるか、サンプリングピクセルの数(楕円の境界平行四辺形)が入力ソース画像の4倍より大きくなるときに起こります。これは現在ユーザーが設定できません。

3D 箱、透視レイヤリング

歪んだ画像全体が正しく配置されたレイヤー(または '仮想キャンバス')に保存されることを保証する 'プラス' 形式の "+distort" は、画像を歪ませるのに使った同じ '制御点' を使えば、それらの点が '仮想空間' で揃うように設計されています。これは、画像が一緒に レイヤーマージ されると、それらの画像も制御点に従って揃うことを意味します。たとえばここでは、2つの画像、'正面' と '背' の画像を生成し、2つの縁の制御点が互いに揃って箱の背を形成するようにします。

  # 背の画像を生成
  magick -size 200x40 xc:skyblue \
    -pointsize 20 -gravity north -annotate +5+0 'IM Examples' \
    -pointsize 10 -gravity south -annotate +0+0 'ImageMagick' \
    -stroke blue -strokewidth 2 -draw 'line 30,0 30,40' \
    -rotate -90 box_spine.jpg

  # 表紙を生成
  magick -size 150x200 xc:skyblue \
    -fill black -pointsize 20 -gravity north -annotate +0+5 'IM Examples' \
    -fill blue -pointsize 15 -gravity northeast -annotate +5+28 'Box Set' \
    -fill black -pointsize 15 -gravity south -annotate +0+5 'ImageMagick' \
    -stroke blue -strokewidth 2 -draw 'line 0,169 150,169' \
    \( logo.gif -resize 100x100 \) \
    -gravity center -compose multiply -composite box_front.jpg

  # 両方の画像を歪ませ、共通の点を使ってマージ。
  magick \
    \( box_spine.jpg -alpha set -virtual-pixel transparent \
       +distort Perspective \
           '0,0 -30,20  0,200 -30,179  40,200 0,200  40,0 0,0' \) \
    \( box_front.jpg -alpha set -virtual-pixel transparent \
       +distort Perspective \
           '0,0 0,0  0,200  0,200  150,200 100,156  150,0 100,30' \) \
    \
    -background black -compose plus -layers merge  +repage \
    -bordercolor black -compose over -border 15x2    box_set.jpg

[IM Output] [IM Output] [IM Output]

ここでも '縁で接する' 部品をつなぐために Plus アルファ合成 を使っていることに注目してください。これは2つの画像の間に '半透明の隙間' が生成されるのを防ぐために必要です。詳細は上の 3D 立方体 の例と、マスクされた2つの画像の整列 を参照してください。このような位置を使うことは、'背' 画像のほぼすべてが実際には負の 'x' 位置に歪まされることを意味します。そのため結果画像は仮想キャンバス上に負のオフセットを持ちます。オペレータのレイヤリング "+distort" 版を使うとき、IM はこれを問題なく行えます。レイヤーマージ オペレータも、負のオフセットを持つ画像をレイヤー化するよう設計されており、2つの画像をきれいに 'つなぎ合わせ' ます。マージされた後、最終画像からその負のオフセットを除去するために、最後の "+repage" をまだ使う必要があります。そうしないと、ウェブブラウザのような他のプログラムがそうした負のオフセットを理解できず、未定義の効果を引き起こすかもしれません。上の例はまた、ダウンロードしてもっと便利に遊べるように、シェルスクリプト "[box_set_example](../static/img/scripts/box_set_example)" にも入れてあります。これをさらに進めて、'箱' が載っている面に映る鏡像も加えられますが、それをより写実的にするために、その画像を何らかの方法で再着色したり暗くしたりするとよいでしょう。そうした鏡像技法については 反射 を参照してください。
PHP でのさらなる例が、縁なしのキャンバスフレームに '写真' をラップする議論で開発されました。詳細は キャンバスラップ変換 を参照してください。
最後に、www.animecoversfan.com のための Jean-François Hren による素晴らしい例を紹介します。これは IM 討論フォーラム で盛んに議論されました。

[Diagram]

この画像は、アニメビデオの箱のカバーの芸術的な画像を取り、そのカバーを3つのセグメント('カバー'、'背'、'裏') に分割し、それぞれを別々にレイヤー画像へ歪ませ、4番目の 'ディスク' 画像を加え、一緒にマージして作られました。その後、画像は(HardLight 画像合成を使った)ハイライトと陰影効果の追加、そして(CopyOpacity を使った)境界と半透明の影効果の追加で仕上げられました。さらに驚くべきは、その全プロセスが入力画像から単一の "magick" コマンドで行われたことです。これは IM にできることの優れた例であり、複雑なコマンドスクリプトを生成するプロセスの例でもあります。フォーラムの議論 を読むことをお勧めします。多くのヒント、コツ、一般的なデバッグ技法が含まれています。(投稿された例をさらに歓迎します)

透視射影(Perspective Projection)歪み

'[Affine](#affine)' 歪みが '[Affine Projection](#affine_projection)' の数学的係数を与えることで直接扱えるのと同様に、'[Perspective](#perspective)' も 'Perspective Projection' 歪みの8つの係数で扱えます。以前と同様、これらの数値は、ソース画像の点を宛先画像へ 順方向マッピング するために使われる係数を表します。すなわち、ソース画像 x,y を宛先画像 i,j へマッピングするために使われる数学的な値です。8つの浮動小数点引数は(与える順序で)… sx, ry, tx, rx, sy, ty, px, py


これらの係数値が今度は式を形成します… Xd = | sx*Xs + ry*Ys + tx | , | Yd = | rx*Xs + sy*Ys + ty |
---|---|---|---|---|---


|


px*Xs + py*Ys + 1.0 | px*Xs + py*Ys + 1.0
ここで "Xs,Ys" はソース画像座標、"Xd,Yd" は宛先画像座標です。内部的には、ImageMagick Distort は上記の方程式を逆にして、適切な 逆ピクセルマッピング を行い、"Xd,Yd" 座標をソース画像の "Xs,Ys" の色参照へマッピングします。'Perspective Projection' の最初の6つの値は、実際には '[Affine Projection](#affine_projection)' の係数と同じですが、より論理的になるようわずかに並べ替えられています('マトリックス数学' の用語では、最初の6要素が対角に転置されています)。追加の2つの引数 px,py は、歪み全体へのスケーリング除数を形成し、これにより画像が、与えられた値に応じた特定の方向に小さく見えるようになり、歪んだ画像に透視の '距離' 効果を与えます。これら2つの値がゼロに設定されると、'Perspective Projection' 歪みは 'Affine Projection' と等価になります。たとえば… |

  magick rose: -alpha set -virtual-pixel transparent \
          -distort Perspective-Projection \
             '1.40, 0.25, 3.0    0.15, 1.30, 0.0    0.007, 0.009' \
          perspective_projection_rose.png

[IM Output]
あなたが与えるマトリックスは順方向の透視マトリックスで、ソース画像座標を宛先画像座標へマッピングすることを覚えておいてください。内部的には、ImageMagick はマトリックスを逆にして、宛先画像座標をソース画像座標へマッピングできるようにします。それらの値が何かを見たい場合は、Verbose 歪みオプション を使って、IM にその内部係数を FX オペレータ式 として出力させます(次を参照)。

透視の内部

透視歪みの直前に "-verbose"(上の 詳細な歪みの概要 を参照)を加えると、IM は "-distort" オペレータのほぼ等価な置き換えとなるはずの2つのオペレータを出力します。一つは非常に遅い "-fx" 版です(FX DIY オペレータ を参照)。もう一つは順方向マッピングの Perspective_Projection マトリックスです。たとえば… |

  magick rose: -alpha set -virtual-pixel transparent -verbose \
          -distort Perspective "0,0,3,0 0,46,10,46 70,0,70,7 70,46,60,40" \
          +verbose perspective_rose.png

[IM Output]
| [IM Text]


最初のセクション Perspective Projection は、ソース座標を宛先座標へマッピングするのに使えます。式は上記のとおりです。

i = ( 1.430099*x +0.246650*y +3 )/( 0.006757*x + 0.009448*y +1 ) j = ( 0.147296*x +1.434591*y +0 )/( 0.006757*x + 0.009448*y +1 )


これらの値を抽出して使う例は、歪んだレイヤー画像の配置 の最後の一連の例に示されています。一方、2番目の FX 等価セクションは、別の8つの係数のセットを使い、画像歪みが実際に適用する必要のある 逆ピクセルマッピング を実行します。すなわち…

x = ( 0.711858*i -0.108326*j -2.135575 )/(-0.004119*i -0.005877*j +1 ) y = (-0.073090*i +0.699571*j +0.219269 )/(-0.004119*i -0.005877*j +1 )


出力された FX 等価 式では、除数の係数が X と Y の両座標の方程式に共通なので、最初に使われることに注意してください。あなたが与えるすべての座標はピクセル座標ではなく画像座標であることを覚えておいてください。詳細は 画像座標対ピクセル座標 を参照してください。そのため、どのピクセル位置も、上記を適用する前に入力ピクセル座標に 0.5 を加える必要があり、それから最終座標から 0.5 を引いてピクセル(描画)座標に戻します。これが上の FX 等価 コードで適用されているのを見られます。FX 等価の最後のテストは、ソース画像参照の直前で、宛先がソース画像に正しくマッピングできない無効な '空' のピクセルを処理します。ただしそれは、そうしたピクセルに "-mattecolor" の代わりに単に 'blue' を代入し、透視歪みのために内部アルゴリズムが提供する地平線アンチエイリアスは一切提供しません。
透視順方向マッピングの例… これらのマッピングにより、一方の画像の特定の座標を他方の画像の位置へ(どちらの方向にも)変換できます。たとえば、ソースのバラ画像の中心にある暗い点はピクセル座標 '39,20' にあります。それを画像座標にマッピングするには ½ を加えて '39.5,20.5' を得ます。今、x,y から i,j への方程式を使って、それを宛先画像座標 '44.2,24.1' へマッピングできます。そして最後に '描画' ピクセル座標へは ½ を引いて最終位置 '43.7,23.6' を得ます。そしてここで、その座標を入力画像と出力画像の両方に円で印を付けます…

  magick rose: -fill none -stroke black \
          -draw 'circle 39,20 39,24'    rose_marked.png

  magick perspective_rose.png -fill none -stroke black \
          -draw 'circle 43.7,23.6 43.7,26.6'  perspective_rose_marked.png

[IM Output] [IM Output]

ご覧のとおり、透視歪みされた画像の同じ点が、両方の画像で(サブピクセルレベルに至るまで)正しく配置されています!

バイリニア歪み

'Bilinear' 歪み手法は、別の種類の4点歪みを実装します。しかしこれは、上で見た '[Perspective](#perspective)' 歪みほど単純ではありません。しかし、後で見るように、非常に有用な代替の歪みです。

順方向バイリニア歪み

たとえば、グリッドが重ねられたマンドリルの特別なテスト画像を取り、それを透視とバイリニアで歪ませてみましょう。

  magick mandrill_grid.jpg -alpha set -virtual-pixel black \
       -distort Perspective \
              '0,0 26,0   128,0 114,23   128,128 128,100   0,128 0,123' \
       mandrill_pers.jpg
  magick mandrill_grid.jpg -alpha set -virtual-pixel black -interpolate Spline \
       -distort BilinearForward \
              '0,0 26,0   128,0 114,23   128,128 128,100   0,128 0,123' \
       mandrill_blin.jpg

[IM Output]
元画像 | | [IM Output]
透視 | [IM Output]
バイリニア
---|---|---|---

まず、両方の歪みが画像をある制御点のセットから別の点のセットへ正しくマッピングしたことに気づくはずです。また、ソース画像のすべての水平・垂直の線は、両方の歪みで直線のまま保たれます。しかし、類似点はそこで終わります。透視は線の間隔を縮小して、対角線でさえも直線のまま保ちます。これにより正方形の面積が小さくなり、右上の角に写実的な '遠くにある' 見た目を与えます。一方バイリニアは、画像の片側を 'より遠くに' 見せることはせず、線を直線に保とうともしません。それがしようとするのは、すべての線の間隔を一定に保つことですが、これにより対角線が曲がってしまいます。すなわち、どの線に沿っても距離の比率を保ちます。つまり、各線分の相対的な長さは、線が全体として曲がったり、湾曲したり、短縮されたりしても、線の全長にわたって同じままです。これは、上の例でグリッド間隔が画像全体で一定のスケールを保ち、右上の歪んだ正方形が左下の歪んだ正方形とほぼ同じサイズのままであることを意味します。画像は '平らに見える' まま、ただ別の形に歪まされます。(順方向)バイリニアは、元画像のどの水平・垂直の線も最終画像で直線のまま保つことを保証することに注意してください。すなわち、直交整列された矩形を、指定された四辺形へ変換し、元の矩形の各辺が線全体で一定のスケーリングを保ったまま直線を保ちます。歪みのこの側面が、'BilinearForward' 歪みをはるかに複雑な 'グリッド' 歪みで有用にします。すなわち、隣り合う2つの '四辺形' が、たとえ非常に異なって歪まされても、縁と縁が正しく揃うからです。ここに '[Perspective](#perspective)' と '[BilinearForward](#bilinear_forward)' の別の比較があります。組み込みのバラ画像の非常に激しい歪みを使います…

  magick rose: -alpha set -virtual-pixel transparent \
          -distort Perspective "0,0,3,0 0,46,10,46 70,0,70,7 70,46,60,40" \
          perspective_rose.png
  magick rose: -alpha set -virtual-pixel transparent -interpolate Spline \
          -distort BilinearForward "0,0,3,0 0,46,10,46 70,0,70,7 70,46,60,40" \
          bilinear_rose.png

[IM Output]
元画像 | | [IM Output]
透視 | [IM Output]
バイリニア
---|---|---|---

(すべての直線を保つという)目標を達成するために、透視歪みは画像のほぼ全体を右側のより小さな領域へ '吸い込む' ように見えますが、一方バイリニア歪みは、中央のバラをその結果でも中央に保ちました。ここでも距離の比率を保ち、バラを左右の縁の間で等間隔に保ちました。それが行ったのは、画像の高さをその長さに沿って線形に垂直に圧縮することだけでした。'BilinearForward' 歪みのこの側面は、それが 'トラペゾイダル(台形)' 歪みとしても知られる理由です。すなわち、一方向だけがスケーリングされるとき、画像を一方向に線形に圧縮するだけです。その圧縮方向は、一つの軸に沿って整列するのではなく、傾けることすらできます。 | _'BilinearForward' 歪みを実行するのに必要な逆ピクセルマッピングの複雑さのため、エリアリサンプリング は現在オフになっていることに注意してください。

そのため、極端な圧縮(2倍以上)の領域では、いくらかのエイリアシング効果が現れる可能性があります(上の例の線の縁を参照)。ただし、スーパーサンプリング、または '-interpolate Spline' を使って、最終画像の品質を改善できます。
---|---
| _IM v6.5.7-0 より前は、'BilinearForward' 歪みはまだ開発中で、特定の '退化' したケースに問題があり、特定の状況で 'black' のエラー画像を引き起こすことがありました。

---|---

逆方向バイリニア歪み

水平・垂直の線だけが直線のまま保たれるので、'BilinearForward' 歪みを使って歪みを逆にすることはできません。変換された画像のグリッド線はもはや水平でも垂直でもないので、結果画像で直線のまま保たれないからです! たとえば座標ペアを入れ替えて、'順方向' 歪みを再適用しても(上で '[Perspective](#perspective)' 歪みを使って行ったように)、元画像を復元できません。

  magick mandrill_blin.jpg -alpha set -virtual-pixel black \
       -distort BilinearForward \
              '26,0 0,0   114,23 128,0   128,100 128,128  0,123 0,128' \
       mandrill_blin_back.jpg

[IM Output] [IM Output]

指定された実際の座標は実際に正しく自身を配置しましたが、画像の歪みは逆にされていないことに注意してください。要約すると、'[BilinearForward](#bilinear_forward)' 歪みはそれ自身の逆ではありません。画像を復元するには、わずかに異なるが密接に関連した歪みを使う必要があります。'幾何学的変換' の数学的な逆は 'BilinearReverse' 歪みとして実装されています。たとえば…

  magick mandrill_blin.jpg -alpha set -virtual-pixel black \
       -distort BilinearReverse \
              '26,0 0,0   114,23 128,0   128,100 128,128  0,123 0,128' \
       mandrill_blin_rev.jpg

[IM Output] [IM Output]

| 前述のとおり、'[BilinearForward](#bilinear_forward)' 歪みの複雑さのため、エリアリサンプリング は現在オフになっており、上記では深刻なエイリアシング効果を引き起こしています。
---|---
'[BilinearReverse](#bilinear_reverse)' は 'BilinearFoward' と同じ距離比率保存の特徴を持ちますが、任意の四辺形を直交整列された矩形へ変換し、四辺形の辺が垂直・水平の整列にマッピングされたときに直線のまま保たれることを保証します。上でご覧のとおりです。 | IM v6.5.1-2 より前は、'BilinearReverse' 歪みは単に 'Bilinear' として実装されていました。
---|---
バイリニア歪みのいくつかの実装(古いバージョンの IM や Leptonica ライブラリ を含む)は、上記のより単純な(逆方向の)版のバイリニア歪みだけを実装していました。しかしそのような歪みは、矩形画像を '順方向マッピング' するのにあまり適していません。たとえばここでは、おそらく '[BilinearForward](#bilinear_forward)' 歪みを使うべきだった歪みに '[BilinearReverse](#bilinear_reverse)' を使ってみます。

  magick mandrill_grid.jpg -alpha set -virtual-pixel black \
       -distort BilinearReverse \
              '0,0 26,0   128,0 114,23   128,128 128,100   0,128 0,123' \
       mandrill_blin_rev2.jpg

[IM Output] [IM Output]

ご覧のとおり、宛先の四辺形が直交矩形でなかったため、画像は激しく歪まされ、多くの内側に湾曲する線を生み出しました。

タイル状バイリニア歪み

さて、'[BilinearReverse](#bilinear_reverse)' は矩形から '湾曲した' 画像を生み出します。その効果は、湾曲した3次元に見える面を生成するように見える、興味深いタイルパターンを生み出します。たとえば上の 遠い地平線を眺める で使ったのと同じ変換を適用すると、この興味深い結果が得られます。 |

  magick checks.png  -virtual-pixel tile  -mattecolor DodgerBlue \
          -distort BilinearReverse \
               '0,0 20,60  90,0 70,63  0,90 5,83  90,90 85,88' \
          bilinear_rev_tile.png

[IM Output]
実のところ '[BilinearReverse](#bilinear_reverse)' は決して '地平線'(無効ピクセル)を生み出しません。一方、'[BilinearForward](#bilinear_forward)' を使うと、'空' または '無効ピクセル'(現在の "[-mattecolor](https://imagemagick.org/command-line-options/#mattecolor)" で埋められる)をかなり頻繁に生み出す傾向があります。実際、タイルパターンはかなりおかしくなる傾向があります… |

  magick checks.png  -virtual-pixel tile  -mattecolor DodgerBlue \
          -interpolate Spline  -distort BilinearForward \
               '0,0 20,60  90,0 70,63  0,90 5,83  90,90 85,88' \
          bilinear_fwd_tile.png

[IM Output]
| 前述のとおり、'[BilinearForward](#bilinear_forward)' 歪みの複雑さのため、エリアリサンプリング は現在オフになっており、上記では深刻なエイリアシング効果を引き起こしています。
---|---
そのため、タイル状形式の '[BilinearForward](#bilinear_forward)' の使用は推奨しません。ただし、順方向歪みを使うときは、'空' の予期しない灰色のパッチの出現を防ぐために、適切な "[-mattecolor](https://imagemagick.org/command-line-options/#mattecolor)" を定義することをお勧めします。

バイリニアの内部

'順方向マッピングバイリニア歪み を使ってソース画像の座標を宛先画像へマッピングする実際の式は… Xd = C0*Xs + C1*Ys + C2*Xs*Ys + C3 , Yd = C4*Xs + C5*Ys + C6*Xs*Ys + C7
しかし IM は 逆ピクセルマッピング 技法を使って歪みを実装するので、上記の式を逆にする必要があります。これは二次方程式の解法、平方根、そして1ページ分の代数を必要とする複雑なプロセスです。IM に FX 等価を Verbose で出力させると、この複雑さを見られます。たとえば前に作った checks 画像を使うと…
  magick checks.png -alpha set -virtual-pixel transparent -mattecolor none \
      -interpolate Spline -verbose -distort BilinearForward \
                   '0,0,0,0  0,90,0,90  90,0,60,30  90,90,90,90' \
      +verbose bilinear_checks.png

[IM Output]
| [IM Text]


'FX 等価' の最後の行にある '(rt > 0 ) ? red :' のチェックは、無効な負の平方根を避けるためです。これが、前の例で示された '空' 効果を生み出すチェックです。一方、逆方向バイリニア歪み ははるかに単純で、より単純な多項式の方程式を直接適用して、前の歪みを逆にできます… |

  magick bilinear_checks.png  -virtual-pixel transparent \
      -verbose -distort BilinearReverse \
                   '0,0,0,0  0,90,0,90  60,30,90,0  90,90,90,90' \
      +verbose bilinear_checks_rev.png

[IM Output]
| [IM Text]


ご覧のとおり、結果の方程式は非常に単純です。今度は宛先座標をソース画像座標へ 逆ピクセルマッピング するために適用しているからです。 上で見られるエイリアシング効果は '[BilinearForward](#bilinear_forward)' によって生じており、'[BilinearReverse](#bilinear_reverse)' 歪みによるものではありません。これは、'順方向' マッピング版ではその複雑さのため、現在 エリアリサンプリング がオフになっているからです。
さらに読みたい方は、Leptonica アフィンおよび透視変換 を案内します。

結合バイリニア歪み

作成中

2つのバイリニア歪み手法を一緒に使うと、四辺形の辺を直線に保ちつつ、任意の四辺形を別の任意の四辺形へ直接歪ませられます。本質的には、まず一つの四辺形を矩形画像へ 'Reverse' 歪みし、それからその矩形を最終的な四辺形へ 'Forward' 歪みできます。この種の歪みはまた、座標の任意の矩形グリッドを、別の座標の矩形グリッドへ歪ませられることを意味します。これは 'グリッド' 歪みとして知られています。この技法はイメージモーフィングの主要な基礎です。イメージモーフィングでは、2つの画像の上に線の矩形グリッドを定義し、それらを使って画像を中間の合成へマージしたり、ある画像から別の画像へ適切にモーフィングするアニメーションを生成したりします。しかしこれはまだ実装されていませんが、追加が予定されています。


多項式歪み(多項式フィットを使った歪み)

'Polynomial' 歪みは、これまでのほとんどの歪み手法と同様に制御点のペアをマッピングしますが、標準的な多項式の方程式を使います。これは、制御点が与えられる前に、もう一つ余分な引数が必要なことを意味します。

Order X1,Y1 I1,J1 X2,Y2 I2,J2 X3,Y3 I3,J3 X4,Y4 I4,J4 . . . .

'Order' 引数は通常 '1' 以降の整数ですが、特別な値 '1.5' も使えます。これは、('x' と 'y' の両方を使う)2次元の数学的方程式の 'order'、つまり複雑さを定義し、それが適用されます。たとえば order '1' の多項式は、次の形の方程式を適合させます… Xd = | C2x*Xs + C1x*Ys + C0x | , | Yd = | C2y*Xs + C1y*Ys + C0y |
---|---|---|---|---|---
これを アフィン射影 に使われる方程式と比較すると、それが等価であることがわかるでしょう。X と Y の各式に3つの定数が必要なので、少なくとも3つの X,Y 座標ペアを与える必要もあります。それ以上あると、方程式が与えられた座標に最小二乗フィットされます。次の 'order' あるいは '1.5' は '[BilinearReverse](#bilinear_reverse)' と等価です(方程式が宛先座標をソース画像へマッピングするのに使われることを覚えておいてください)。 Xd = | C3x*Xs*Ys + C2x*Xs + C1x*Ys + C0x | , | Yd = | C3x*Xs*Ys + C2y*Xs + C1y*Ys + C0y |
---|---|---|---|---|---
'[BilinearReverse](#bilinear_reverse)' 歪みと同様に、最低4つの座標が必要です。たとえば… 基本的にこれは order '1' の方程式とまったく同じですが、多項式の方程式に1つ余分な項が加えられています。すなわち、各方程式が軸ごとに4つの項を持ち、4つの定数があるので、IM がそれらの定数を割り出せるよう、少なくとも4つの座標ペアが必要です。

  magick mandrill_grid.jpg -alpha set -virtual-pixel black \
       -distort Polynomial \
              '1.5   0,0 26,0   128,0 114,23   128,128 128,100   0,128 0,123' \
       mandrill_poly_1.5.jpg

[IM Output] [IM Output]

order '2' では、多項式の方程式はさらに拡張されて完全な二次フィットになり、最低6つの座標ペアが必要です。 Xd = C5x*Xs2 + C4x*Xs*Ys + C3x*Ys2 + C2x*Xs + C1x*Ys + C0x
Yd = C5y*Xs2 + C4y*Xs*Ys + C3y*Ys2 + C2y*Xs + C1y*Ys + C0y
基本的にこれは order '1' の方程式とまったく同じですが、多項式の方程式に3つの余分な項(order 2 + 1)が先頭に加えられています。すなわち、各方程式が今や6つの定数を持つ6つの項を持つので、IM がそれらの定数を割り出せるよう、少なくとも6つの座標が必要です。これ以降の各順次 order の多項式は、方程式のペアそれぞれにさらに 'order'+1 の項を加えます。そのため、order '3' の3次フィット多項式は完全に定義するのに最低10の座標ペアを必要とし、order '4' の5次フィット多項式は15の座標ペアを必要とします。詳細な歪みの概要 を使って、多項式歪みが指定された座標に適合させた結果の方程式を見られます。より大きな例として、グリッドの画像があります。また、そのグリッドをどうワープしたいかについての大きな座標のセット(ファイル "[grid16_control_points.txt](../static/img/images/grid16_control_points.txt)" に保存)もあります。それから IM に、入力座標に 'best-fit' する3次多項式を生成するよう要求しました。
  # 画像をワープ
  magick grid16.png -virtual-pixel gray \
          -distort polynomial "3 $(cat grid16_control_points.txt)" \
          grid16_polynomial.png

  # 画像座標の順序を逆にする
  awk '{print $3, $4, $1, $2}' grid16_control_points.txt \
                             > grid16_cp_inverse.txt

  # 画像を再びワープして戻す
  magick grid16_polynomial.png -virtual-pixel gray \
          -distort polynomial "3 $(cat grid16_cp_inverse.txt)" \
          grid16_restored.png

[IM Output] [IM Output] [IM Output]

小さな "awk" スクリプトは、元の X,Y 制御点ペアのセットを取り、その順序を逆にするので、新しいファイルを使って歪みを '元に戻す' ことを試みられます。 | _制御点ファイル "[grid16_control_points.txt](../static/img/images/grid16_control_points.txt)" の座標は画像座標です。つまり、各数値はそれが指すピクセルの中心を指します。追加の 0.5 がなければ、値は整数の 'ピクセル座標' になります。上の 画像座標対ピクセル座標 を参照してください。

値は画像ビューアを使った手作業の参照だけで決定されたので、実際にはあまり正確ではありません。これが逆歪みアーティファクトの一部の原因かもしれませんが、多項式方程式の機能的な 'best-fit' が全体的な歪み効果を減らしているはずです。


---|---
これは、多項式歪みが機能し、うまく機能するものの、正確でも可逆でもない歪みであることを示しています。本質的に、81の座標が一緒に '平均化' されて、入力座標の数学的な 'best-fit' を生成します。必要な最小数(10)よりも多くの制御点(81)が与えられたため、どの制御点も要求された座標に正確に一致することは保証されません。しかしこの特定の例では、座標が期待される歪み結果に近いので、それなりに近いはずです。多項式関数は一般に、画像の縁、特に角で最も多くの誤差を持ちます。これはピクセルの位置だけでなく、縁でのサンプリング領域(EWA)にも影響します。これは使われる近似の自然な結果です。より高い order の多項式を使うこともできましたが、この場合それは大きな改善をもたらしません。この特定のケースでは、多項式は実際には非多項式の三角関数に自身を適合させようとしています。それらの関数の性質のため、2番目の歪みは最初のものよりも不正確になります。この例は実際には、下で見る放射状の バレル歪み 手法と非常に密接に関連しています。ただし、マッピングされる座標は実際にはグリッド配置である必要はなく、任意の座標マッピングのセットでよいことに注意してください。このため、地理学者が、町、交差点、山頂、その他の目印の既知の位置を制御点として使い、航空写真を地球物理学的な地図と整列(および重ね合わせ)するためによく使われます。 |
多項式歪み は一般に非可逆なので、IM が与えられたソース画像に対する宛先画像のビューポートの 'best-fit' を計算することはできません。そのため、オペレータの "[+distort](#distort_bestfit)" 形式は機能せず、通常の "[-distort](https://imagemagick.org/command-line-options/#distort)" 演算にフォールバックします。ただし、歪みビューポート オプションを使って宛先画像のビューポートを定義することはできます。_
---|---


円形・放射状歪み手法

これらは、歪みのプロセスの主要な構成要素として放射状ベクトルの使用を伴う歪みです。

Arc 歪み(画像を円弧へ曲げる)

'Arc' 歪み(IM v6.3.5-5 以降)は、はるかに複雑な 極座標歪み(後述)の単純なバリエーションです。デフォルトでは、与えられた画像を与えられた角度にわたって完全な円弧に曲げ、他の引数なしでは、画像の水平中心線のスケーリングと画像のアスペクト比の両方を、可能な限り保とうとします。これを行うために、最大4つの引数を取ります。

_arc_angle rotate_angle top_radius bottom_radius_

ただし "_arc_angle_" だけが必須で、他の引数はオプションで、与えられた順序で必要に応じて追加できます。たとえば画像を60度の角度にわたって 'Arc' します… |

  magick rose: -virtual-pixel White -distort Arc 60  arc_rose.jpg

[IM Output]
| _他の画像歪みオペレータとは異なり、'Arc' 歪みは常に、完全なソース画像が存在するように結果画像のサイズを設定することに注意してください。これにはアンチエイリアスの縁のピクセルも含まれます。そのため、結果画像が入力画像のサイズに一致することはめったにありません。

ビューポート歪みオプション だけが、特定の歪みに対して結果画像のサイズを変えられます。_
---|---
2番目の引数 "_rotate_agle_" を加えると、画像を円の周りで回転できます。たとえば90度回転します。 |

  magick rose: -virtual-pixel White -distort Arc '60 90'  arc_rose_rot.jpg

[IM Output]
特定の半径引数が指定されていないので、'Arc' 歪み手法は元画像のスケールをできるだけ保とうと大変な努力をします。これを行うために、画像の水平中心線が、ソース画像の幅と与えられた "_arc_angle_" の '理想半径' に設定されます。これは、画像をより大きな "_arc_angle_" にわたって arc すると、使われる中心線の半径も同じ係数で縮小することを意味します。そのため、中心線の半径はより小さくきつくなります。 |

  magick rose: -virtual-pixel White -distort Arc 120  arc_rose_3.jpg

[IM Output]
画像が今やより小さな円に収まるが、画像の下端はさらに小さな円になっていることに注目してください! 画像を arc する角度をさらに大きく設定すると、下端は歪みの中心、そしてその先まで到達し、その結果ソース画像の下部が忘却の彼方へ消えていきます。

  magick rose: -virtual-pixel White -distort Arc 60   arc_rose_1.jpg
  magick rose: -virtual-pixel White -distort Arc 90   arc_rose_2.jpg
  magick rose: -virtual-pixel White -distort Arc 120  arc_rose_3.jpg
  magick rose: -virtual-pixel White -distort Arc 180  arc_rose_4.jpg
  magick rose: -virtual-pixel White -distort Arc 240  arc_rose_5.jpg
  magick rose: -virtual-pixel White -distort Arc 300  arc_rose_6.jpg
  magick rose: -virtual-pixel White -distort Arc 360  arc_rose_7.jpg

[IM Output] [IM Output] [IM Output] [IM Output] [IM Output] [IM Output] [IM Output]

完全な円のリングへの Arc

長い画像は、非常に大きな角度にわたってずっとうまく 'Arc' 歪みします。たとえば、長い画像(テキストメッセージなど)をリングにラップできます。そして、ここで何が起きているか本当に見られるように、異なる 仮想ピクセル 背景色を設定して、元画像の境界が見えるようにしました。

  magick -font Candice -pointsize 20 label:' Around the World ' \
          -virtual-pixel Background  -background SkyBlue \
          -distort Arc 60     arc_circle_1.jpg
  magick -font Candice -pointsize 20 label:' Around the World ' \
          -virtual-pixel Background  -background SkyBlue \
          -distort Arc 120    arc_circle_2.jpg
  magick -font Candice -pointsize 20 label:' Around the World ' \
          -virtual-pixel Background  -background SkyBlue \
          -distort Arc 180    arc_circle_3.jpg
  magick -font Candice -pointsize 20 label:' Around the World ' \
          -virtual-pixel Background  -background SkyBlue \
          -distort Arc 270    arc_circle_4.jpg
  magick -font Candice -pointsize 20 label:' Around the World ' \
          -virtual-pixel Background  -background SkyBlue \
          -distort Arc 360    arc_circle_5.jpg

[IM Output] [IM Output] [IM Output] [IM Output] [IM Output]

そして、なんと、ラベル画像を完全な円に 'arc' しました。完全な円画像の接合をよく見ると、接合が完全には完了していない小さなピクセルの線が見えるかもしれません。これは、取り囲む 'SkyBlue' 仮想ピクセル 背景の効果によって生じます。実質的に画像の2つの縁を接合しているからです。完全な円を生成するときは、これら2つの縁を正しく '接合' する仮想ピクセル手法を使う必要があります。これは通常、Tile のようなタイリング 仮想ピクセル 手法の一つを使って行われます。 |

  magick -font Candice -pointsize 20 label:' Around the World ' \
          -virtual-pixel Tile -background SkyBlue \
          -distort Arc 360   arc_circle_tile.jpg

[IM Output]
残念ながら、ご覧のとおり、これは画像を適切に接合するだけでなく、画像の重複した線を主リングへ出入りするように生成してしまいます。良くありません。IM v6.4.2-6 以降、新しい 仮想ピクセル 手法 HorizontalTile がこの問題を解決します。この手法は画像を横方向にのみタイリングするので、円にした画像に良い接合を作りますが、タイルの上下の領域は現在の背景色で埋め、完璧なテキストの円を生み出します。 |

  magick -font Candice -pointsize 20 label:' Around the World ' \
          -virtual-pixel HorizontalTile -background SkyBlue \
          -distort Arc 360   arc_circle.jpg

[IM Output]
画像を 'arc' する前に入力画像を上下逆さまに回転すると、画像の元の '上' を円の内側の縁に置けます。もちろん、その後に結果を再びまっすぐ '回転' し直したいかもしれませんが、その機能はすでに 'Arc' 歪み手法に組み込まれています。 |

  magick -font Candice -pointsize 20 label:' Around the World ' \
          -virtual-pixel Background -background SkyBlue \
          -rotate 180 -distort Arc '270 180'  arc_flip.jpg

[IM Output]
3番目の引数 "_top_radius_" は、計算される '理想' 中心線半径を上書きするので、画像の上部が与えられた半径の円になります。これは幅100ピクセルのリングを作りますが、アンチエイリアス効果を考慮して、収容する画像は幅102ピクセルになります。 |

  magick -font Candice -pointsize 20 label:' Around the World ' \
          -virtual-pixel HorizontalTile -background SkyBlue \
          -distort Arc '360 0 50'  arc_radius.jpg

[IM Output]
画像は依然として同じアスペクト比のままなので、上記は本質的に以前と同じですが、要求された半径の円に収まるようにスケーリングされただけです。半径は浮動小数点にできますが、arc の中心は常にピクセルの '角' に整列するので、結果画像は依然として偶数ピクセル幅になることを覚えておいてください。4番目の "_bottom_radius_" 引数を与えると、リングの幅、つまりその '放射状の高さ' を完全に制御できます。 |

  magick -font Candice -pointsize 20 label:' Around the World ' \
          -virtual-pixel HorizontalTile -background SkyBlue \
          -distort Arc '360 0 45 30'   arc_inner.jpg

[IM Output]
これは画像の放射状スケーリングを歪ませ、放射状スケーリングを結果画像の 'arc 幅' あるいは角度から実質的に分離します。言い換えれば、元画像のアスペクト比はもはや保たれません。入力画像の下端を歪みの中心、つまり '極' でラップして、円の内側を完全に埋めるよう強制することすらできます。 |

  magick -font Candice -pointsize 20 label:' Around the World ' \
          -virtual-pixel HorizontalTile -background SkyBlue \
          -distort Arc '360 0 45 0'   arc_fill.jpg

[IM Output]

Arc 歪みの例

Arc 歪み を使って興味深い効果を生成できます。たとえば、やや長いチェッカーボードパターンを(仮想ピクセル 設定 '[HorizontalTile](misc.html#horizontal_tile)' を使って)リングに arc すると… |

  magick -size 210x30 pattern:checkerboard -alpha set \
          -virtual-pixel HorizontalTile -background SkyBlue \
          -distort Arc 360   arc_checks.png

[IM Output]
デフォルトの 仮想ピクセル 設定 '[Edge](misc.html#edge)' を使うと、より興味深い効果を生み出せます。 |

  magick -size 210x30 pattern:checkerboard  -virtual-pixel Edge \
          -distort Arc 360   arc_checks_edge.png

[IM Output]
もちろん '[Tile](misc.html#edge)' 設定も興味深い '放射状' 効果を生成し、円形のチェッカーボードパターンを生成できます。 |

  magick -size 210x30 pattern:checkerboard  -virtual-pixel Tile \
          -distort Arc 360   arc_checks_tile.png

[IM Output]
上記は、結果画像の上下の半径を制御することでさらに精細化できます。ここに '[Arc](#arc)' 歪みの例をもう少し示しますが、どう機能するかを把握するのはあなたにお任せします。何を思いつけますか? |

  magick -size 90x1 pattern:gray50 -scale 900x100 -normalize \
          -virtual-pixel Tile  -set option:distort:viewport 100x100-50-50 \
          -distort Arc 360  +repage  arc_radii.gif

[IM Output]
|

  magick -size 400x100 pattern:hs_diagcross \
          -virtual-pixel Tile  -set option:distort:viewport 100x100-50-50 \
          -distort Arc '360 0 80 0' +repage  arc_cross.gif

[IM Output]
|

  magick -size 360x80 xc: -draw "fill none stroke black line 0,5 360,80" \
          -virtual-pixel White  -distort Arc '360 0 50 0'  arc_spiral.gif

[IM Output]

|

  magick tree.gif -set option:distort:viewport 120x60-60-60 \
          -virtual-pixel Dither  +distort Arc '180 0 25 0' \
          +repage arc_rays.gif

[IM Output]
この最後の例の '光線' は、疑似ランダムな '[Dither](misc.html#dither)' 仮想ピクセル 設定の副産物で、元画像の左上角からの '太陽' 色の奇妙なピクセルパターンによる結果です。同じディザリング効果はまた、'木' 画像を取り囲む円形の '破線' の線も生み出します。'[Edge](misc.html#edge)' 設定を、興味深い縁のピクセルを加えるよう修正した画像とともに使うことで、この効果のより制御された版を実現できます。

Arc の中心点の配置

デフォルトでは '[Arc](#arc)' は、画像が持つかもしれないどんな 仮想キャンバス オフセットも完全に無視し、画像が arc された '中心' の位置を報告すらしません。しかし、'中心点' の位置を知ることは非常に有用です。"-distort" の代わりに特別なプラス形式 "+distort" を使うと、画像には 仮想キャンバス が与えられ、中心が仮想キャンバスの原点に配置されます。言い換えれば、画像の '0,0' 点が arc の '中心' に設定されます。これは特に、完全な円より小さな角度で arc された画像を配置するのに有用です。そこでは arc の '中心' は画像の中心ではありません。たとえば… |

  magick logo: -resize x150 -gravity NorthEast -crop 100x100+10+0! \
          \( -background none label:'IM Examples' \
             -virtual-pixel Background +distort Arc '270 50 20' \
             -repage +75+21\! \)  -flatten  arc_overlay.jpg

[IM Output]
ここではテキストラベルを作り、オペレータのプラス "+distort" 形式を使って不完全な円に '[Arc](#arc)' 歪みしました。arc の '中心' は、画像の仮想キャンバスオフセットを使って IM が慎重に保存しました。これは、'!' フラグ付きの "-repage" を使ってオフセットの相対調整を単に行うだけで、結果のテキストの円を好きな場所に配置できることを意味します! たとえば上の例で、ピクセル座標 75,21 にある魔法使いの帽子の先端などです。残念ながら、画像を配置するのに仮想オフセットが使われるため、正確な配置は整数ピクセルサイズに制限されます。2回目の歪みを行わずに、Arc 歪み をサブピクセルで定義された位置に配置することはできません。しかし、極座標歪み(次を参照)ではこれができます。

極座標歪み(完全な円の歪み)

'Polar' 歪み(IM v6.4.2-6 で追加)は、上の '[Arc](#arc)' 歪みのより低レベルな版です。しかしこれは自動的に 'bestfit' を行わず、画像のアスペクト比を保とうともしません。6つのオプションの浮動小数点引数は… Radius_Max Radius_Min Center_X,Center_Y Start_Angle,End_Angle

すべての引数は、空白で区切られた位置でオプションです。デフォルトでは 'CenterX,Y' は入力画像領域のちょうど真ん中になります。それから、上端全体が中心になり、下端が円の外側を完全に取り囲むようにラップされる、完全な円の極座標画像が生成されます。左右の縁は、中心点の上で角度 '-180' から '+180' の画像で出会います。'Radius_Max' は与える必要があるので、何らかの正の値であるべきです。ただし '0' の値を与えると、中心と最も近い縁の間の距離に設定されるので、他の値が与えられなければ(デフォルト)、入力画像全体が画像の真ん中の円にマッピングされます。たとえば、世界地図をすべてデフォルトを使って極座標ビューへ変換してみましょう。もちろん、完全な円の極座標マッピングを生成するときは、'[HorizontalTile](misc.html#horizontal_tile)' の 仮想ピクセル 設定を指定すべきです…

  magick worldmap_sm.jpg -virtual-pixel HorizontalTile  \
          -background Black   -distort Polar 0   polar_arctic.jpg

[IM Output] [IM Output]

もちろんこれは南半球を激しく歪ませ、南極大陸を 'ディスクワールド' の円周全体にラップします。ソース画像を回転して、極冠だけを示すように切り抜くことで、南極大陸の素敵な地図を生成できます。より見やすくするためにより大きな出力半径も指定し、歪みオペレータ の 'プラス' 形式を使って IM に出力画像をこのサイズに 'フィット' するよう要求しました。 |

  magick worldmap_md.jpg -rotate 180 -crop 100%x25%+0+0 +repage \
          -virtual-pixel HorizontalTile -background Black \
          +distort Polar 80 +repage  polar_antarctica.jpg

[IM Output]
上記は厳密には正しい地球のビューではないことに注意してください。デカルト地図は球の表現であり、極座標の画像ではないからです。特別な 'Radius_Max' 値として正確に '-1' を使うと、歪んだ画像の半径は、中心から最も遠い角(対角線)までの距離に設定されます。これは、次に見る完全な画像の '[DePolar](#depolar)' 歪みに対する理想的な '逆' を提供するためです。(使用例については下の (De)Polar トリック を参照)。 | '[Arc](#arc)' 歪みとは異なり、'[Polar](#polar)'('デカルトから極座標へ' の歪みとしても知られる)は、ソース画像の '理想的な' アスペクト比を保とうとはしないことを覚えておいてください。注意が必要です。
---|---
'CenterX,Y' 引数は、結果画像の中心をサブピクセルオフセットに配置するのに最も有用です。すなわち、中心がピクセルの境界(整数)にあるか、ピクセルの中心(0.5 オフセット付き)にあるかです。もちろん、これは仮想キャンバス 'レイヤー' の位置も決定します。ただしデフォルトでは、画像の真ん中(入力画像をビューポートとして使う "-distort" の場合)か 0,0("+distort" レイヤー画像の場合)の値が割り当てられます。次の引数 'Start_Angle,End_Angle はさらに使われることが少なく、入力画像が覆う角度を制限し、デフォルトでは -180 から 180 度の値になります(0 は真下)。'[Arc](#arc)' 歪みと同様に、これを使って結果の極座標画像を回転できます。しかしこれは '弧' を生成するのにも使えます。たとえば…

  magick worldmap_sm.jpg -virtual-pixel Black -background Black \
          +distort Polar  '60,20 0,0 -60,60' +repage  polar_arc.jpg

[IM Output] [IM Output]

現在 IM は結果のレイヤー画像のサイズを縮小せず、要求どおり、仮想画像の原点が座標 0,0 にあるように整列されることに注意してください。引数のスタイルを除けば、これが '[Arc](#arc)' と '[Polar](#polar)' 歪みの最大の違いです。また、左の縁(角度 -60)が左にあることにも注意してください。これは 'Y' 軸が下向き(すべての画像回転と同じ)であることを考えれば、数学的に正しいのです。もちろん Arc と同様に、仮想ピクセルのタイリング効果を使って繰り返しパターンを生成できます。たとえば、これは最後の例とまったく同じですが、'[HorizontalTileEdge](misc.html#horizontal_tile)' 設定を使ったものです… |

  magick worldmap_sm.jpg -virtual-pixel HorizontalTile -background Black \
          +distort Polar  '60,20 0,0 -60,60' +repage  polar_arc_tiled.jpg

[IM Output]

DePolar 歪み(極座標からデカルトへ)

これは本質的に '[Polar](#polar)' 歪みの逆で、まったく同じオプション引数のセットを持ちます。6つのオプションの浮動小数点引数は…

Radius_Max Radius_Min Center_X,Center_Y Start_Angle,End_Angle

ここでも 'Radius_Max' が '0' に設定されると、'CenterX,Y' から最も近い縁までの距離が使われ、これは最大の完全な円の中にあるものが、入力画像と同じサイズの画像に収まるようマッピングされることを意味します。たとえば、前の 'ディスクワールド' をデカルト地図に戻してみましょう。

  magick polar_arctic.jpg  -distort DePolar 0  world_restored.jpg

[IM Output] [IM Output]

入力画像のサイズが2つの歪みを通してずっと保たれているので、上記の結果は基本的に元の地図とまったく同じです。もちろん画像は上の '極' と半径の両方で圧縮されたので、出力は予想よりずっとぼやけています。 実際、エリアリサンプリング アルゴリズム(EWA)が円弧でピクセルをサンプリングできないため、さらに悪くなっています。そのため、"[DePolar](#depolar)" 歪みでは エリアリサンプリング がオフになっています。次のセクションで示すような何らかの スーパーサンプリング 技法を代わりに使うことをお勧めします。
IM に 'bestfit'(オペレータの "+distort" 形式を使用)を使わせると、'Radius_Max' を等倍スケーリングに保つように出力画像をリサイズし、幅を 'Radius_Max' と 'Radius_Min' の中間の半径の円周距離に設定します。これは本質的に極座標画像のアスペクト比をできるだけ保とうとしますが、予想より長く細い画像を生み出すことがあります。たとえば。
  magick polar_arctic.jpg  +distort DePolar 0  world_restored_2.jpg

[IM Output] [IM Output]

(De)Polar サイクルのトリック(放射状/角度ぼかし)

上で見たように、'Radius_Max' に '0' を使うと、'[Polar](#polar)'(デカルトから極座標へ)歪みを使うとき、画像全体が円にマッピングされることを保証し、同じ設定が '[DePolar](#depolar)'(極座標からデカルトへ)を使ってその円を矩形画像に戻してマッピングします。しかし、矩形画像を '[DePolar](#depolar)' し、それから '[Polar](#polar)' を使って歪みを再び逆にしたい場合、これはあまりうまく機能しません。たとえば、花の画像を取り、de-polar し、それから特別な 'Radius_Max' 値 '0'(半径 = 最も近い縁)を使って復元してみましょう。

  magick flower_sm.jpg -virtual-pixel Black \
          -distort DePolar 0  flower_depolar.jpg
  magick flower_depolar.jpg \
          -virtual-pixel HorizontalTile -background black \
          -distort  Polar  0  flower_circle.jpg

[IM Output] [IM Output] [IM Output]

今、画像は最初の '[DePolar](#depolar)' 歪みでクリップされたため、適切に復元されていません。それでもこれ自体は有用な技法で、入力画像とは完全に独立した方法でサイズ調整された、既存の画像のための完璧な円形マスクを生成するのに使えます。この '[DePolar](#depolar)'-'[Polar](#polar)' サイクル技法を正しく行うには、中心から最も遠い角までの距離である半径を使う必要があります。特別な 'Radius_Max' 値 '-1' は、IM に '中心点' から最も遠い角を半径として計算し使うよう求めます。

  magick flower_sm.jpg  -virtual-pixel Black \
          -distort DePolar -1  flower_depolar-1.jpg
  magick flower_depolar-1.jpg \
          -virtual-pixel HorizontalTile -background black \
          -distort  Polar  -1  flower_restored.jpg

[IM Output] [IM Output] [IM Output]

復元された画像はわずかにぼやけていますが、これは '[DePolar](#depolar)' 演算中に画像全体を保つために必要だった半径の圧縮によって生じます。しかしそれは、適切な スーパーサンプリング 技法を使って修正できます(次の一連の例を参照)。しかし、なぜ画像をこの形に変換して戻したいのでしょうか? それは、画像の中間の 'DePolar' 版に他の歪みを適用することで、非常に手の込んだ放射状または角度の効果を非常に簡単に生成できるからです。たとえば中間画像をロールすることで、出力画像を回転できますが、角がいくらかクリップされることがあります… |

  magick flower_sm.jpg -virtual-pixel Black -distort DePolar -1 \
          -roll +15+0 \
          -virtual-pixel HorizontalTile -background Black \
          -distort  Polar  -1  flower_polar_rotate.jpg

[IM Output]
回転の方向が Rotate オペレータSRT 歪み とは逆になっていることに注意してください。

Depolar-Polar サイクルの問題

上の画像回転で、回転した画像の縁に沿っていくつかの '階段状' の歪みに気づいたかもしれません。これはよく知られた問題で、画像の大きな円周を入力画像のより小さな '幅' に圧縮することによって生じます。たとえばここでは、チェッカーボードテスト画像を取り、変更を一切加えずに通常の Depolar-Polar サイクルに通すだけです。

  magick checks.png   -virtual-pixel Transparent \
          -distort DePolar -1   checks_depolar.png
  magick checks_depolar.png  -virtual-pixel HorizontalTile -background None \
          -distort  Polar  -1   checks_cycled.png

[IM Output] [IM Output] [IM Output]

中間画像の点に、画像圧縮によって生じたエイリアシング効果がはっきり見えます。これはまた、その最初の '[Depolar](#depolar)' による入力画像の変換中に通常の エリアリサンプリング が使われないという事実によって悪化しています。この問題を解決する最良の方法は、Distort 出力スケーリング を使って中間画像を拡大し、それから最終画像を縮小することです。これにより、上で見た圧縮アーティファクトを除去する スーパーサンプリング された結果が得られます。たとえば、これはより良い 'no-op' depolar-polar サイクルを一つのコマンドで行ったものです… |

  magick checks.png -virtual-pixel Background -background None \
          -set option:distort:scale 4  -distort DePolar -1 \
          -noop \
          -virtual-pixel HorizontalTile -background None \
          -set option:distort:scale .25 -distort  Polar  -1 \
          checks_cycled_ss.png

[IM Output]
ご覧のとおり、ひどいエイリアシング効果はほぼ消えました。ただし、非常に背の高い細い画像では問題が再び現れる可能性があることに注意してください。最良の方法は、これを 'ランドスケープ' すなわち横長の画像に、上で示したスーパーサンプリングとともに制限することです。あとは "-noop" オペレータを、探している放射状・回転効果を生成する適切なコマンドに置き換えるだけです。

Depolar-Polar 効果の例

では、より良い 極座標回転 を、今度はスーパーサンプリングを使って再び示します。ただし、中間画像が4倍大きいので、画像ロール の量も4倍大きくする必要があることに注意してください。 |

  magick flower_sm.jpg   -virtual-pixel Black \
          -set option:distort:scale 4   -distort DePolar -1 \
          -roll +60+0   \
          -virtual-pixel HorizontalTile -background Black \
          -set option:distort:scale .25 -distort Polar -1 \
          flower_polar_rotate_ss.jpg

[IM Output]
ご覧のとおり、縁に沿った '階段状' 効果が除去され、はるかに高品質な画像結果になりました。
あるいは、中間画像に単純な線形ぼかしを適用できます(画像を圧縮して再び拡大することで実現)。 |

  magick flower_sm.jpg -virtual-pixel Black \
          -set option:distort:scale 4   -distort DePolar -1 \
          -scale 10%x100%\! -filter Gaussian -resize 1000%x100%\! +filter \
          -virtual-pixel HorizontalTile -background Black \
          -set option:distort:scale .25 -distort Polar -1 \
          flower_angular_blur.jpg

[IM Output]
結果は画像の '回転ぼかし' に非常によく似ています。これは、誤った名前の付いた 放射状ぼかしオペレータ に似ていますが、まったく同じではありません。実際、結果はその特化したぼかし手法よりも高品質です。適用されたさまざまな形式の 仮想ピクセル設定 で 'black' 色を使うと、縁がわずかに暗くなりますが、上記の場合はそれほど悪くありません。'black' の縁の効果を除去する一つの方法は、代わりに 'transparency' 色を使い、それから終わったらアルファチャンネルを完全にオフにして、IM が計算した実際の色だけを残すことです。もう一つは、2つの 'edge' 仮想ピクセル手法('[Edge](misc.html#edge)' と '[HorizontalTileEdge](misc.html#horizontal_edge)')を使うことで、これは画像の縁を未定義の仮想キャンバス空間へ拡張します。 |

  magick flower_sm.jpg -virtual-pixel Edge \
          -set option:distort:scale 4   -distort DePolar -1 \
          -scale 10%x100%\! -filter Gaussian -resize 1000%x100%\! +filter \
          -virtual-pixel HorizontalTileEdge -background Black \
          -set option:distort:scale .25 -distort Polar -1 \
          flower_angular_blur_edge.jpg

[IM Output]
これは縁の近くではるかに良い結果を示します。
極座標版の画像を垂直にぼかすことで、今度はリサイズ圧縮ではなく モーションぼかしオペレータ を使って、画像の中心から外側へ動く 放射状の筋 を生成できます… |

  magick flower_sm.jpg   -virtual-pixel Black \
          -set option:distort:scale 4   -distort DePolar -1 \
          -virtual-pixel Edge   -motion-blur 0x28-90 \
          -virtual-pixel HorizontalTile -background Black \
          -set option:distort:scale .25 -distort Polar -1 \
          flower_radial_blur.jpg

[IM Output]
結果が画像のハイライト(花びら)だけをぼかすようにするには、これを元画像と Lighten を使って合成し、ぼかされたより明るい色だけが見えるようにします。暗い色がより明るい領域へぼやけて、花の真ん中の黄色い点を壊すことがありません。 |

  magick flower_sm.jpg  flower_radial_blur.jpg \
          -compose Lighten -composite   flower_radial_blur_lighten.jpg

[IM Output]
これを行う別の例については 星と彗星 も参照してください。ただしそこでは、'[Polar](#polar)' 歪みを適用する前に、中間の 'DePolar' 画像を直接生成しています。DePolar-Polar サイクルの特別な使用法と、これらの歪みが矩形画像に対して完全に可逆であることを保証するよう私に強く求めてくれたことに対し、Fred Weinhaus に特別な感謝を捧げます。彼はこの技法を、"[bump](http://www.fmwconcepts.com/imagemagick/bump/index.php)"、"[ripples](http://www.fmwconcepts.com/imagemagick/ripples/index.php)"、"[striations](http://www.fmwconcepts.com/imagemagick/striations/index.php)" を含む、彼の多数の ImageMagick スクリプト で見事に活用しています。

バレル歪み(レンズの歪みを補正する)

バレル歪み(IM v6.4.2-4 で追加)は、写真でカメラレンズによって生じる球面歪みを補正するために特別に設計されています。すなわち、バレルやピンクッション効果のような歪みで、これらは実質的に互いの逆です。レンズ歪み補正にこのオペレータを使う実際の応用については、レンズ補正 セクションを参照してください。この歪みは、その後消えてしまったウェブサイトで Helmut Dersch 教授 が定義した、ABCD として知られる4つの係数値のセットに基づいて実装されています。Wayback Machine によるサイトのアーカイブを Correcting Barrel Distortion で見られます。値は基本的に次のような歪みの方程式を形成します…

_R src_ = r * ( A*_r 3_ + B*_r 2_ + C*_r_ + D )

ここで "_r_" は宛先の半径、"_R src_" はピクセル色を取得するソースピクセルです。半径は、入力画像の最小の幅または高さの半分で radius = '1.0' になるよう正規化されています。これは逆に思えるかもしれませんが、それは結果画像の完全なカバレッジを保証するために 逆ピクセルマッピング 技法が使われるからです。4つの係数(ABCD)はすべて、特定のカメラ、レンズ、ズームの組み合わせに対して固定されています。これら3つすべては通常、EXIF プロファイル で画像とともに保存されます。これは重要です。なぜなら、いったんカメラのこれらの値を得れば、それらを使って、そのカメラとレンズの組み合わせで撮影されたすべての写真に存在する球面レンズ歪みを除去できることを意味するからです。'**Barrel**' 歪み手法に必要な引数。一般に3つまたは4つの値だけを与えます…

_A B C_ [ _D_ [ _X_ , _Y_ ] ]

オプションの X, Y 引数は、放射状歪みのオプションの '中心' を提供します。さもなければ、与えられた画像のちょうど中心(その仮想オフセットにかかわらず)がデフォルトになります。係数は、4つの A から D の値すべてが '1.0' に合計されると、画像の最小の幅/高さが変わらないように設計されています。このため、(画像全体のスケーリングを制御する)D が与えられない場合、4つの値すべてが '1.0' に合計されるように設定されます。パラメータ '0.0 0.0 0.0'(_A_ =_B_ =_C_ =0.0_D_ =1.0' と等価)を使うと、入力画像に変化が生じず、これはこの歪みの 'no-op' 引数です。ここに元のウェブサイトからの例があり、写真を撮るのに使われたカメラの提供された係数を使っています。

  magick barrel_distorted.jpg -virtual-pixel black \
          -distort Barrel "0.0 0.0 -0.075 1.1" \
          barrel_distorted_fixed.jpg

[IM Output] [IM Output]

画像の歪みが補正され、建物の柱がまっすぐになったことに注目してください。ただし、4つの係数が 1.0 より大きい値に合計されたため、画像はわずかに縮小され、上下の縁の中央に小さな黒い領域が生じました(与えられた 仮想ピクセル設定 に従って)。ここに、各入力係数に 0.2 を加える効果があります。ここでも値は 1.0 より大きく合計されるので、結果の歪んだ画像は小さくなります。

  magick checks.png -virtual-pixel gray \
          -distort Barrel "0.2 0.0 0.0 1.0"   barrel_checks_A.png
  magick checks.png -virtual-pixel gray \
          -distort Barrel "0.0 0.2 0.0 1.0"   barrel_checks_B.png
  magick checks.png -virtual-pixel gray \
          -distort Barrel "0.0 0.0 0.2 1.0"   barrel_checks_C.png
  magick checks.png -virtual-pixel gray \
          -distort Barrel "0.0 0.0 0.0 1.2"   barrel_checks_D.png

[IM Output] [IM Output] [IM Output] [IM Output]

0.2 を引くと逆の効果が生じますが、結果をよりよく見られるように、より大きな 'D' 値を使って(画像を縮小して)効果をオフセットしました。

  magick checks.png -virtual-pixel gray \
          -distort Barrel "-0.2 0.0 0.0 1.3"   barrel_checks-A.png
  magick checks.png -virtual-pixel gray \
          -distort Barrel "0.0 -0.2 0.0 1.3"   barrel_checks-B.png
  magick checks.png -virtual-pixel gray \
          -distort Barrel "0.0 0.0 -0.2 1.3"   barrel_checks-C.png
  magick checks.png -virtual-pixel gray \
          -distort Barrel "0.0 0.0 0.0 1.3"    barrel_checks-D.png

[IM Output] [IM Output] [IM Output] [IM Output]

A の値が B より大きな効果を、BC より大きな効果を生み出し、D は結果の全体的なスケーリングを提供することに注目してください。これにより、各係数を使って画像を調整し、外側の縁では一つの歪みを、真ん中に向かっては別の歪みを補正できます。一方はピンクッション、他方はバレル、という具合に。非常に汎用的です。上記の係数(ABCD)は、画像の最小の幅または高さの半分の '正規化' された半径で機能するよう設計されています(極座標歪み の '0' 半径設定のように)。すなわち、画像サイズに依存しません。そのため、特定のカメラが生成する任意の画像に対して、その品質サイズ(カメラ設定)や、画像をより小さくリサイズしたかどうかにかかわらず、同じ値のセットを使えます。各係数に適切な乗数/除数を使って、最大の幅/高さの半分や対角線の半径を使うなど、他の '正規化' された半径値を使うように係数値を調整することも可能です。 | _Helmut Dersch はまた、写真の歪み補正には LAB 色空間を使うことを検討すべきだと指摘しています。より良い色補間を生み出すからです。これは実際にはすべての歪み(Resize を含む)に当てはまるかもしれません。

テストでは、LAB 空間は sRGB と同じくらい非線形ですが、極端な値がクリップされたときの色の歪みの可能性を避けることがわかっています。人間の色知覚 と、色空間補正を伴うリサイズ の実用的な例を参照してください。_
---|---

x 軸と y 軸に異なる係数のセットを宣言することもでき、いくつかの珍しい歪みを生成できます。

_A x Bx Cx Dx Ay By Cy Dy_ [ _X_ , _Y_ ]

別々の X と Y 引数の使用は、Fred Weinhaus の pinbarrel スクリプトでプロトタイプ化されました。ただし彼の引数は逆順で、D が最初、A が最後です。正の C 値を、'y' の係数セットだけに適切な D 値とともに使うことで、画像を真ん中で垂直に膨らむように歪ませられます。 |

  magick rose: -alpha set -virtual-pixel transparent \
          -distort Barrel "0.0 0.0 0.0 1.0   0.0 0.0 0.5 0.5" \
          barrel_bulge.png

[IM Output]
同様に、負の C 値を使うと、画像を真ん中で 'つまむ' ことができます。 |

  magick rose: -alpha set -virtual-pixel transparent \
          -distort Barrel "0.0 0.0 0.0 1.0   0.0 0.0 -0.5 1.9" \
          barrel_pinch.png

[IM Output]
あるいは、X 係数に逆の効果を加えることで、画像を指でつまんでいるように見せ、両側を膨らませられます。 |

  magick rose: -alpha set -virtual-pixel transparent \
          -distort Barrel "0.0 0.0 0.5 0.5   0.0 0.0 -0.5 1.9" \
          barrel_pinch_2.png

[IM Output]

BarrelInverse 歪み(代替のバレル歪み)

'BarrelInverse' 歪み手法は、前の バレル歪み 手法と非常に似ており、実際に同じ引数のセットを取ります。ただし、適用される式はわずかに異なり、方程式の主要部分が半径で除算します。すなわち方程式が反転されています。

_R src_ = r / ( A*_r 3_ + B*_r 2_ + C*_r_ + D )

| この方程式は 'Barrel' 歪みの '逆' を生み出しません。これを使って前の歪みを '元に戻す' ことはできません。
---|---
この結果、ABC の '負' の形式を、D の同等の調整とともに使って、似ているがわずかに異なる結果を実現します。研究論文 レンズ歪み補正の手法(PDF) のようないくつかの情報源は、この形式のレンズ補正歪みでより良い結果が実現できると示唆しています。たとえば、ここに前の 'Pinch' の例をこの形式の歪みを使って等価にしたものがあります。 |

  magick rose: -alpha set -virtual-pixel transparent \
          -distort BarrelInverse "0.0 0.0 -0.5 1.5   0.0 0.0 0.3 0.5" \
          barrel_inv_pinch.png

[IM Output]


透視歪み

これらは、ある面に存在する画像を別の面に投影またはマッピングするために使われる歪みです。投影線は平行でも、特定の位置から放射状でもありえます。技術的には アフィン透視歪み も、ある平らな面の画像を別の平らな面に(それぞれ平行投影と放射投影を使って)'投影' するという点で '透視的' ですが、それらは非常に一般的なので、上の独自の例領域でより詳しく見ています。ここでは、通常は IM 討論フォーラム の助けを借りて実装された、より珍しい '透視歪み' を見ます。

Cylinder 2 Plane

'Cylinder2Plane' 歪みは、円筒の中心の点から、その円筒に接する平らな平面への放射状の透視歪みです。

[diagram]

この配置は、P.90 カメラ として知られる特殊なピンホールカメラに典型的なものです。そこでは90度の弧の写真が、カメラ内で円筒を形成するフィルムに捉えられます。ここにそのようなカメラからの写真の例があります…

[photo]

この問題は、結果画像が歪んでおり、フィルムの物理的配置のために直線が湾曲した弧になることです。本質的には、'点' 投影源(ピンホール)の周りに自身を巻き付ける湾曲した面です。通常のピンホールカメラには、点源から平らな面に投影しているので、この問題がないことに注意してください。'Cylinder2Plane' 歪みは、画像を円筒配置から平らな平面に投影することで、これを修正します。次のパラメータを取ります…

_fov_angle center_x,y fov_output dest_center_x,y_

最初のパラメータ、カメラの視野の角度だけが必須です。P.90 カメラは 90mm(放射状)の焦点距離と標準的な 57mm 幅のフィルムを使い、これが今度は 90 / 57 * 180/pi つまり 90.467 度の '視野' を生み出します。たとえばここでは、P90 写真を平面に投影して、画像をより '通常' に見せ、直線を再びまっすぐにします。

  magick p90_orig.jpg -virtual-pixel Gray \
          +distort Cylinder2Plane 90.467  p90_plane.png

[IM Output]

歪みの 'プラス' 版を使って元画像のすべての歪んだピクセルを示すので、画像の幅と高さの両方が変わったことに注意してください。投影のために幅が広くなり、一方、垂直中心線に沿ったその実際の画像の高さは変わりませんでした。写真とアルゴリズムは IM 討論 湾曲したフィルム面の補正 からのものです。この討論はまた、別の討論 ピンホールカメラのアルゴリズム的ビネット補正 へとも流れ込みました。
特別な 'fov_output' が与えられると、出力画像の幅(通常はビューポートサイズ)がこの角度に正確に一致するように結果の出力画像をスケーリングします。ビューポートが与えられない場合、画像の縁を整数に整列したまま、画像の 1:1 スケーリングをできるだけよく近似する best match が有効になります。歪みの中心点パラメータ(入力の接点と地平点)。最後の '中心' パラメータは、ビューポート画像 'レイヤー' における結果の正確な浮動小数点配置(すなわちサブピクセル平行移動)を制御します。これは 'center_x,y' パラメータとともに、より大きな画像から部分を抽出できます。たとえば、より大きな360度パノラマ画像から小さな90度ビューを抽出します。将来: 360 パノラマから小さな平らな '視聴' 画像を抽出することと、それら360度をゆっくりパンするアニメーション。

Plane 2 Cylinder

'Plane2Cylinder' 歪みは上記の投影の逆で、次のパラメータを取ります…

_fov_angle center_x,y_

たとえば、これは前の P.90 カメラの例を元に戻します。

  magick p90_plane.png -virtual-pixel Black \
          +distort Plane2Cylinder 90.467  p90_restored.png

[IM Output]

結果には前に加えられた余分なピクセルがまだ含まれており、さらに多くを加えます。これらは上記の結果からトリミングすべきです。ここではこの歪みを使って、フィルムのスプロケットの縁の穴を備えた 'フィルムストリップ' のアニメーションを生成します。

  magick -size 12x12 xc: -draw 'circle 6,6 6,2' -negate \
          -duplicate 5 +append +duplicate \
          rose: +swap -background black -append \
          -duplicate 3 +append \
          -virtual-pixel HorizontalTile -background SkyBlue \
          -duplicate 19  -distort SRT '%[fx:72*t/n],0 1 0 0,0' \
          -distort Plane2cylinder 115 \
          -bordercolor Skyblue -border 0x3 -set delay 5 \
          film_strip_anim.gif

[IM Output]

説明:

  • まず穴の画像が描画され、複製して付加し、6つの穴のシーケンスを作ります。それから再び複製します。
  • 組み込みのバラ画像が加えられ、これらのスプロケット穴の2つのコピーの間に挟まれて(black の塗りつぶしで)付加され、最終的なフィルムストリップの単一フレームを作ります。
  • これは複製されて4フレームのフィルムストリップを作り、最終画像の長さを定義します。
  • SRT '平行移動' 歪みを使って20フレームのアニメーションが作られます。Distort アニメーション を参照してください。
  • それから、それら20フレームのそれぞれが、115度の弧にわたって円筒に歪まされ、フィルムストリップの無限の水平タイルを生成するために仮想ピクセル設定を使います。
  • この場合の角度は入力画像の幅のためだけのもので、最終画像の幅は180度より大きくなります。歪みの 'プラス' 版を使わなかったからです。そのため、歪んだ幅は幅方向に縮小しますが、出力画像は縮小しません。
  • 最後に境界が加えられ、アニメーション設定が適用されます。

多点・フリーフォーム歪み

Shepard's 歪み(タフィーのような歪み)

Shepard の手法(IM v6.4.2-4 で追加)は、与えられた制御点の動きを使って、'局所的' 効果の観点から画像を歪ませます。これは、ソース画像を表す 'タフィー' の厚いブロックにピンを打ち込み、それからピンを動かすのと等価だと考えられます。より技術的には、逆二乗距離補間 の観点で点を動かします。制御点が1つだけ使われると、当然画像全体が動かされ(平行移動され)、1点 '[Affine](#affine)' 歪みで得られるのと同じです。あまり面白くありません。では2つの制御点を動かしてみましょう。たとえば 'koala' の耳('30,11' と '48,29')を引っ張って拷問してみましょう…

  magick koala.gif -virtual-pixel Black \
          -distort Shepards '30,11 20,11  48,29 58,29' \
          koala_ear_pull.png

[IM Output] [IM Output]

ご覧のとおり、制御点の動きのために、2つの制御点の間の画像の部分が引き伸ばされました。しかし、制御点自体に近い画像や、画像の下部などを含む、画像の他の部分はほぼそのまま残されました。あまり目立たないかもしれませんが、制御点の遠い側の部分も圧縮されるので、遠ざかるにつれて、制御点が結果に及ぼす影響が小さくなります。すなわち、この歪みは '局所化' された歪みを生成します。これをよりよく見られるように、視点を(歪みビューポート を使って)広げてみましょう… |

  magick koala.gif -virtual-pixel Black \
          -set option:distort:viewport 115x115-20-20 \
          -distort Shepards '30,11 15,11  48,29 58,29' \
          +repage koala_ear_pull_2.png

[IM Output]
ご覧のとおり、引き伸ばされたコアラの '頭' に合わせて、画像の形も歪まされました。この効果を避けるには、画像の角と、おそらくいくつかの縁も 'ピン留め' して、動かないようにするのがより一般的です。 |

  magick koala.gif -virtual-pixel Black \
          -set option:distort:viewport 115x115-20-20 \
          -distort Shepards '30,11 15,11  48,29 58,29
              0,0 0,0  0,74 0,74   74,0 74,0  74,74 74,74' \
          +repage koala_ear_pull_3.png

[IM Output]
他の点(この場合は角だけ)をピン留めしながら1点だけ動かすことも有用です。たとえばコアラの鼻('28,24' にある)を画像の真ん中へ動かしてみましょう。 |

  magick koala.gif -virtual-pixel Black \
          -distort Shepards '28,24 37,37
              0,0 0,0  0,74 0,74   74,0 74,0  74,74 74,74' \
          +repage koala_move_nose.png

[IM Output]
この特定の例は特別です。Fred Weinhaus が彼の1点 'アニメーションモーフィング' スクリプト "[shapemorph](http://www.fmwconcepts.com/imagemagick/shapemorph/)" に使った歪みだからです。ただし彼の元のスクリプトは、Shepards 歪み がまだ IM に追加されていなかったため、遅い DIY FX オペレータ を使っていました。このスクリプトは実際、Shepards 歪み の元のアイデアの源でした。

画像の領域を動かす

その領域の周りの点のセットを一緒に動かすことで、画像のセクション全体を動かすことすらできます。たとえば、頭の周りの点(赤い線)を使ってコアラの頭を横に動かしますが、動かしたくない画像の部分(緑の線)もピン留めします。

  magick koala.gif -virtual-pixel Black -distort Shepards \
            '19,8, 29,8   19,27 29,27   26,34 36,34
                 33,37 43,37   36,37 46,37   53,37 63,37   58,25 68,25
             13,20 13,20  17,28 17,28  25,36 25,36
                 35,39 35,39   46,40 46,40   50,43 50,43 ' \
          +repage koala_head_move.png

[IM Output] [IM Output]

頭が動かされた一方で、頭の縁がひどく歪まされていることに注意してください。その理由は、歪みが領域ではなく点を動かすからです。それらの縁を示す点が離れすぎていると、画像はそれらの点の間で、タフィーやゼリーのように、滴ったり、漏れたり、曲がったりします。(余談: 実際の用語は 'ラバーシート' や '風船' の引き伸ばしです)。また、2つの制御点が近くにあっても、異なる方向や量で動くと、画像はそれらの周りで局所的に渦巻いたり曲がったりすることがあります。制御点は依然として正しい位置に行き着きますが、その目標を達成するために、それらの周りのすべてがひどくワープされます。そしてそれが頭の縁に沿って起こっていることです。では、縁を示す点はどれくらい近くにあるべきでしょうか? 基本的に、異なる動きをする他の点までの距離の少なくとも半分です。そのため、縁の点を増やすか、固定点と動く点の間に余分な距離を置きます。これを行うことで、画像が引き伸ばされ圧縮されうる空間をよりよく定義できます。また、画像全体も一般に頭とともに左へ動いたことに注意してください。固定されたか、特定の宛先へ動かされた制御点だけが、正しく配置されることが保証されます。どの制御点からも遠い画像の部分も、すべての制御点の動きのおおまかな平均に基づいて動きます。そのため、画像全体に広がる 'fixed' 点をもっと多く持つか、画像の外側いくらか離れたところに負に動かした点を置いて、全般的な平均の動きを相殺するのがより良いです。制御点を複製または重複させて(2回挙げて)、その領域で歪みに対する特定の点の影響や 'パワー' を増やすこともできます。ここに '頭を横に動かす' の別の版がありますが、今回は動く(赤)点と固定(緑)点の間にいくらか余分な分離を与えました。また、歪んだ画像の平均的な全般の動きを減らすために、固定点をもっと多く加えました。

  magick koala.gif -virtual-pixel Black -distort Shepards \
            '15,15, 25,15   19,27 29,27   26,34 36,34
                33,37 43,37   36,37 46,37    53,37 63,37
             10,2 10,2   2,10 2,10   4,55 4,55   14,47 14,47
                25,47 25,47 45,51 45,51   55,45 55,45
                5,70 5,70  15,60 15,60   55,60 55,60   70,70 70,70' \
          +repage koala_head_move_2.png

[IM Output] [IM Output]

上記で最後にすべきことは、上の未定義の黒い領域がどの色になるべきかを設定するために、単により良い "[-virtual-pixel](https://imagemagick.org/command-line-options/#virtual-pixel)" 設定を設定することです。

Shepards と画像の回転

この歪みの一つの側面は、いかなる形の回転も好まないことです! たとえば、ここに PerspectiveBilinearForward の繰り返しを、Shepards 歪み と並べて示します。

  magick mandrill_grid.jpg -alpha set -virtual-pixel black \
       -distort Perspective \
              '0,0 26,0   128,0 114,23   128,128 128,100   0,128 0,123' \
       mandrill_pers.jpg

  magick mandrill_grid.jpg -alpha set -virtual-pixel black -interpolate Spline \
       -distort BilinearForward \
              '0,0 26,0   128,0 114,23   128,128 128,100   0,128 0,123' \
       mandrill_blin.jpg
  magick mandrill_grid.jpg -alpha set -virtual-pixel black -interpolate Spline \
       -distort Shepards \
              '0,0 26,0   128,0 114,23   128,128 128,100   0,128 0,123' \
       mandrill_shep.jpg

[IM Output]
元画像 | | [IM Output]
透視 | [IM Output]
バイリニア | [IM Output]
Shepards
---|---|---|---|---

他の2つの歪み手法と比べて、Shepards 歪み が非常に湾曲した画像を生み出したことに注目してください。それは、与えられた制御点に近い領域で画像を正確に保とうとするからです。そしてそれには画像の回転も含まれます。この '保存' の結果として、グリッドは実際の制御点で 'ortho(直交)' なまま残るように湾曲します。それは、制御点の 'ピン' が実際には丸いピンではなく '十字' で、画像を保持する 'ゼリー' や 'ラバーシート' に画像の回転も保存させているようなものです。これはまた、この歪みが生み出せる多くの '渦巻く' 効果の源でもあります。たとえば、画像の2つの点を取り、それらを互いに通り過ぎるように押すと、画像は回転ではなく渦巻きます。たとえば、コアラの耳を引き離すのではなく、互いに向かって押してみましょう。

  magick koala.gif -virtual-pixel Black \
          -distort Shepards '30,11 40,11  48,29 38,29' \
          koala_ear_push.png

[IM Output] [IM Output]

Shepard's パワー係数

通常、Shepard の IWD(逆加重距離)の距離の重みは逆二乗則(1/r2)に従いますが、IM v6.8.0-10 以降、エキスパート define 'shepards:power' を使って、全体的な重みの 'パワーレベル' を制御できます。定義されない場合、値は 2.0 ですが、より小さく定義することで、歪んだ画像の全体的な平均変位から、動かされた制御点の周りでより局所化された歪みを生成できます。より大きな値を使うと、制御点の周りでより広い影響範囲を生成します。たとえば、ここに 'コアラの耳引っ張り' の例の繰り返しを、歪みの重みに異なるパワーレベルを適用して示します。

  magick koala.gif -virtual-pixel Black -define shepards:power=0.5 \
          -distort Shepards '30,11 20,11  48,29 58,29' \
          koala_ear_pull_pow0.5.png
  magick koala.gif -virtual-pixel Black -define shepards:power=1.0 \
          -distort Shepards '30,11 20,11  48,29 58,29' \
          koala_ear_pull_pow1.png

  magick koala.gif -virtual-pixel Black \
          -distort Shepards '30,11 20,11  48,29 58,29' \
          koala_ear_pull.png
  magick koala.gif -virtual-pixel Black -define shepards:power=3.0 \
          -distort Shepards '30,11 20,11  48,29 58,29' \
          koala_ear_pull_pow3.png
  magick koala.gif -virtual-pixel Black -define shepards:power=8.0 \
          -distort Shepards '30,11 20,11  48,29 58,29' \
          koala_ear_pull_pow8.png

[IM Output]
元画像
と動作 | | [IM Output]
power 0.5 | [IM Output]
power 1.0 | [IM Output]
power 2.0
(デフォルト) | [IM Output]
power 3.0 | [IM Output]
power 8.0
---|---|---|---|---|---|---

上記の画像結果はすべて、まったく同じ制御点の動きのセットを使っています。唯一の違いは、それらの制御点の周りの影響範囲です。小さなパワーは動きを制御点に近い領域だけに '局所化' し、一方より大きなパワーは制御点とともに画像のより多くを引きずります。非常に大きなパワーでは、この引っ張りは制御点の間の中間の線に沿って画像を別々の領域に 'ちぎる' 傾向があります。さらに大きなパワーを使うこともでき、それは単にソース制御点の周りの領域を、宛先制御点の周りの領域へ平行移動するだけです。これらの領域は 'ボロノイ領域' のパターンを形成し、ソース画像の重複したコピーを含むことがあります。たとえば、ここではコアラの鼻(座標 28,24 にある)の周りの領域を、六角形パターンの7つの異なる領域へマッピングし、非常に効率的な方法で '昆虫の目' のような効果を生み出します。 |

  magick koala.gif -virtual-pixel Black -define shepards:power=25 \
          -distort Shepards '28,24 35,35 \
                      28,24 20,10   28,24 50,10 \
                      28,24 20,60   28,24 50,60 \
                      28,24 10,35   28,24 60,35'  koala_hexagonal.png

[IM Output]
Shepards 歪み は実際には、Shepards, Sparse Color オペレータ と同じ技法を使って生成された変位マップ(宛先ピクセルをソース画像へマッピング)と等価であり、これも同じパワー係数の define の影響を受けることを覚えておいてください。

Shepard's 歪み、まとめ

Shepards 歪み は非常に汎用的でフリーフォームな手法で、その歪みを、与えられた点の動きや非動きで示された領域に制限します。その歪みは局所化され、隣り合う制御点の間の距離に従って制限されますが、すべての点は依然として平均化された全般的な効果を持ちます。ただ、この歪みは点駆動であり、線や領域駆動ではないので、異なる動きをする制御点が近くに置かれすぎると、点の間の部分が予期せず膨らんだり渦巻いたりすることを覚えておいてください。それは制御点の間で画像を渦巻かせ、引き伸ばし、圧縮しますが、制御点の近くでは画像を回転したり拡大縮小したりしないよう努めます。そして最後に、どの制御点からも遠く離れた画像の全般的な平均的平行移動を生み出すことがあります。しかし、制御点のブロックが、それらの全般的な相対位置を保ったまま動かせるなら、一般的で非常に単純な点駆動の 'イメージモーフィング' 技法を実装する方法を提供します。Fred Weinhaus のスクリプト 'shapemorph2' は Shepards 歪み を使って、良い汎用の 'アニメーション化されたイメージモーフィング' プログラムを提供します。 内部的には、この歪みは Shepards Sparse Color グラデーション生成器を使って2つの 相対変位マップ を作り、画像を歪ませるのと等価です。これは Fred Weinhaus の元の "[shapemorph](http://www.fmwconcepts.com/imagemagick/shapemorph/)" スクリプトが行うことであり、この歪み技法の源でした。
Shepards 歪み を使う際に必要な計算の複雑さのため、IM はオペレータのプラス "[+distort](#distort_bestfit)" 形式を使ったいかなる形の 'best-fit' 宛先ビューポートも提供しません。ただし、歪みビューポート オプションを使ってより大きな出力画像を定義することはできます。
--- ---
同じ理由で、エリアリサンプリング はオフになっています。そのため、極端な圧縮(2倍以上)の領域では、いくらかのエイリアシング効果が現れる可能性があります。たとえば、最後の例の六角形パターンの縁を参照してください。ただし、スーパーサンプリング を使って結果の最終画像品質を改善し、そうしたエイリアシング効果を減らせます。
--- ---