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

ImageMagick 使用例 -- 画像の畳み込み

ImageMagick 使用例 前書きと索引
畳み込み入門

畳み込みは、ピクセルの局所的な「近傍」を使って画像を変更します。各ピクセルの周囲のすべての色の値を結合し平均することで、画像をぼかしたり、エッジや境界を強調したり、画像をシャープにしたりします。畳み込みの変種である「相関(Correlation)」は、特定のパターンを走査・探索する際にも使われ、画像がどれだけ近く一致するかを示す画像を生成します。


畳み込み入門

Convolve」とそれに密接に関連する「Correlate」メソッドは、多くの点でモルフォロジーに非常によく似ています。実際、ほとんど全く同じように動作し、各位置で近傍「カーネル」をマッチングします。そのため、これらはモルフォロジーの単なる別の特別な「メソッド」と言えます。実際、同じコードの多くを使い、基本カーネルユーザー定義カーネルで定義されたものと同じカーネル定義さえ使っています。このオペレータでの使用を目的とした、より特化したカーネル(その数は多いのですが)については、ぼかしカーネルエッジ検出カーネルを参照してください。最も重要なカーネルは「[Gaussian](../static/img/convolve/gaussian)」カーネルです。しかし、畳み込みはモルフォロジーよりはるかに古く、モルフォロジーが典型的に生成する二値の形状研究効果よりも、グレースケールのグラデーション効果をより多く生み出します。これが、畳み込みがしばしばモルフォロジーとは非常に異なる、あるいは別の操作と見なされ、画像処理においてより中心的なものと見なされる理由です。基本的に、畳み込みや相関は、指定された近傍内のすべてのピクセルの「重み付き平均」を実行します。つまり、各近傍ピクセルの値をカーネルで与えられた量で乗算し、それらの値をすべて加算して最終結果を生成します。このように、最終画像の各ピクセルは一般に、元画像でそれを局所的に取り囲む他のすべてのピクセルの少なくとも一部を含むことになります。別の見方をすると、画像中の各ピクセルの色は、使用するカーネルで定義された通り、近傍のすべての色に加算される(ぼかし)か、減算される(シャープ化/エッジ検出)ことになります。「convolve」と「correlate」は、ごくわずかではあるが重要な点を除いて同じ操作であり、これから見ていく例と制御においては、基本的に同じものとして扱って構いません。後ほど(Convolve と Correlate の比較を参照)、2つのオペレータが実際にどう異なり、なぜそのようにわずかに異なるのかを正確に検討します。しかしほとんどの場合、両者は同じメソッドです。

Convolve ( )

上で述べたように、「Convolve」メソッドは、カーネル内の浮動小数点値に従って局所近傍内の各ピクセルに重み付けすることで動作します。重み付けされた値は単純に加算され、結果画像内の新しい置換ピクセルが生成されます。例えば、非常に小さいユーザー定義の畳み込みカーネルを使って、1つのピクセルを畳み込んでみましょう。特別なカーネル表示設定も設定しているので、定義され使われるカーネルの詳細を見ることができます(表示される画像は拡大されています)。

  magick xc: -bordercolor black -border 5x5 pixel.gif
  magick pixel.gif -define morphology:showKernel=1 \
         -morphology Convolve '3x3: 0.0, 0.5, 0.0
                                    0.5, 1.0, 0.5
                                    0.0, 0.5, 0.0' pixel_spread.gif

[IM Text]

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

ご覧の通り、画像内の1つのピクセルが拡大され、その周囲に50%グレーのピクセルが生成されました。つまり、カーネルの「原点」(この場合はその中心)が元画像内の単一ピクセルの隣に位置すると、その単一ピクセルだけが非ゼロの値を持ちます。このピクセル値はカーネルの「0.5」の値で重み付けされ、結果として得られる「半輝度」ピクセルが結果画像に加算されます。同様に、カーネルの原点が元のピクセルのちょうど真上に位置すると、「1.0」の値が得られ、その周囲の近傍に他の値(黒)が結果に何ら寄与することなく、元のピクセルが再現されます。カーネル値が「0.0」の場合は最終計算に一切関与しないことに注意してください。ゼロ値は事実上「近傍」の一部ではなく、ちょうどモルフォロジーカーネルの「Nan」値が一切関与しないのと同じです。このように、このカーネルは5要素の近傍からなります。多くの点で「[Convolve](#convolve)」メソッドはモルフォロジーの「[Dilate](morphology.html#dilate)」メソッドに非常に似ていますが、「[Dilate](morphology.html#dilate)」はカーネルを一種のビットマップマスクとしてのみ扱い、近傍内の最大値を見つけるだけです。一方「[Convolve](#convolve)」は近傍内のすべての値の重み付き和であり、各カーネル要素の値が全体の結果に関与します。畳み込み操作の構文は次の通りです...

**-morphology Convolve {_畳み込みカーネル_}
**

ただし、より古い、より直接的なオペレータを使うこともできます...

**-convolve {_畳み込みカーネル_}
**

| _IM v6.5.9 より前は、古い「[-convolve](https://imagemagick.org/command-line-options/#convolve)」はモルフォロジーのカーネル定義を理解しませんでした。それはカンマ区切りの値の文字列だけからなる「旧式」のユーザー定義カーネルしか受け付けず、何らかの奇数サイズの正方カーネルを生成しました。現在は「新式」の畳み込みカーネル定義も受け付けます。

ただし、依然として「奇数サイズの正方」カーネルに制限されています。そして、新しい「モルフォロジー」畳み込みメソッドを使い始めるまでは、その状態のままになるでしょう。

_
---|---
| _古い「[-convolve](https://imagemagick.org/command-line-options/#convolve)」オペレータは、新しいモルフォロジーの「[Convolve](#convolve)」メソッドと正確には同じではありません。以下は2つの操作がどう異なるかのリストです...

_

  • _古いオペレータは真の convolve ではなく相関(Correlation)として実装されています。これはカーネルが反転した形で元画像に重ねられないことを意味します。これが結果に与える効果についてはConvolve と Correlate の比較を参照してください。

_ * _奇数サイズの正方カーネルしか受け付けません。モルフォロジーのものは任意の矩形配列を許容し、配列内の任意の点を原点として宣言できます。

_ * _古いオペレータは常にカーネルを正規化し、カーネルのカーネルスケーリングについてユーザーが制御することはできません。新しいものは自動的に正規化はせず、要求する必要があります。ただし、生成されるカーネルのほとんどはあらかじめ正規化されています。

_ * いかなる形の恒等カーネルとのブレンドも使えませんが、出力の出力バイアスは通常通り実行されます。 * _ただし、ホストコンピュータがそのような機能を備えていれば、高速な「GPU」コードを利用します。モルフォロジーはまだこれが有効化されていません。

_ * _現在、他の畳み込み関連オペレータ、例えば「[-gaussian_blur](https://imagemagick.org/command-line-options/#gaussian_blur)」、「[-blur](https://imagemagick.org/command-line-options/#blur)」、「[-sharpen](https://imagemagick.org/command-line-options/#sharpen)」、「[-unsharp](https://imagemagick.org/command-line-options/#unsharpen)」は、オペレータの古いバージョンを使用します。

_ * _デフォルトでは、古いコマンドはカラーチャンネル(「[-channel](https://imagemagick.org/command-line-options/#channel)」設定で定義される)に対してのみ畳み込みを行います。「[-channel](https://imagemagick.org/command-line-options/#channel) RGBA」設定で畳み込みを行うと、アルファチャンネルによってもカーネル値が重み付けされ、透明度に関して正しいぼかしが保証されます。

モルフォロジーの「convolve」メソッドは、デフォルトでカラーチャンネルの透明度の重み付けを自動的に処理します。つまり、これを使った画像のぼかしは、透明な色を透明として扱い、デフォルトでぼかし透明度バグを回避します。

ただし、ユーザーがデフォルトの「[-channel](https://imagemagick.org/command-line-options/#channel)」設定を変更した場合(特別な「Sync」フラグを含めない場合)、畳み込みは純粋なチャンネルベースのグレースケールオペレータとして処理されます。

詳細については「[-channel](https://imagemagick.org/command-line-options/#channel)」設定のドキュメント、または同じフラグを同じ方法で使用する画像チャンネルの数学を参照してください。

_

_

最終的には、新しいモルフォロジーの「[Convolve](#convolve)」メソッドと統合が進むにつれて、上記の違いのほとんどは変わっていくでしょう。

_
---|---
[Convolve](#convolve)」が実際にどのように動作するかの素晴らしい例を見たい場合は、EECE \ CS 253 Image Processing, Lecture 7, Spatial Convolution も見ることをお勧めします。Wikipedia, Convolve の記事には、畳み込み処理の素敵な1次元アニメーションがいくつかあります。

畳み込みカーネルのスケーリング

上記の例は、単一ピクセルのようなほぼ黒い画像にはうまく機能しますが、これを実際の画像に適用すると問題が生じます...

  magick logo: -resize 50% -crop 80x80+150+60 +repage  face.png

  magick face.png \
         -morphology Convolve '3x3: 0.0,0.5,0.0  0.5,1.0,0.5   0.0,0.5,0.0' \
         face_spread.png

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

ご覧の通り、結果画像は元画像よりも非常に明るく(実際には3倍明るく)なっています。何が起きたかというと、各ピクセルが3回共有されているのです。両側の4 × 「0.5」に加えて、元のピクセルの完全なコピーが1つ。つまり、カーネル内のすべての値を加算すると3になり、結果画像が3倍明るくなるのです! 上の「showKernel」出力に戻って見ると、このカーネルが「convolution output range from 0 to 3(畳み込み出力範囲 0 から 3)」を持つと表示されていることがわかります。これは、このカーネルが一般に画像を3倍明るくすることを示しています。これを修正するには、カーネル内のすべての値を3で割りたいでしょう。つまり、「0.5」の値は実際には約「0.1667」であるべきで、中心の値「1.0」は「0.3333」であるべきだったのです。これは「カーネル正規化 」として知られるプロセスです。例えば、これが手動で「正規化」した結果とカーネル定義です...

magick face.png -define morphology:showKernel=1 \
       -morphology Convolve \
       '3x3: 0.0,.1667,0.0  .1667,.3333,.1667  0.0,.1667,0.0' \
       face_spread_norm.png

[IM Text]

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

ご覧の通り、各ピクセルがその直接の近傍それぞれに広がったため、顔画像のごくわずかにぼけたバージョンが得られます。 | _上記で表示されている「カーネル画像」(特別なカーネル→画像スクリプトで生成)も、正規化されたカーネルを示しています。ご覧の通り、カーネル自体は今や非常に暗くなっています。すべての値が暗いものの、それらはすべて加算すると「1.0」の値になるからです。

これ以降、表示されるすべての畳み込みカーネル画像は、常に最大値が白に設定されるよう調整されます。そうしないと、一般に暗くて基本的に役に立たない「カーネル画像」しか見えないからです。

_
---|---
カーネルを自分で正規化するのは楽しいものではなく、ご覧のように結果のカーネル定義をずっと理解しにくくします。そのため、別の方法が提供されています。IM v6.5.9-2 以降、特別なエキスパートオプション「[-define](https://imagemagick.org/command-line-options/#define) convolve:scale={_カーネルスケール_}」を使うと、カーネルにグローバルなスケーリング係数を指定でき、全体結果の明るさを調整できます。 |

magick face.png -define convolve:scale=0.33333 \
       -morphology Convolve '3x3: 0.0,0.5,0.0  0.5,1.0,0.5  0.0,0.5,0.0' \
       face_spread_scale.png

[IM Output]
実際にこれが行うのは、畳み込み結果の全体的な強度の調整です。後の例で見るように、おそらく畳み込み結果をより強く、あるいはより弱くしたくなるでしょう。この「カーネルスケール 」係数を使えばそれができます。

カーネル正規化(自動スケーリング)

(上記のように)スケーリング係数を自分で算出するのではなく、特別な「!」正規化フラグを与えることで、IM にこの「正規化スケーリング係数」を内部的に算出するよう簡単に頼むことができます。 |

magick face.png -define convolve:scale=\! \
       -morphology Convolve  '3x3: 0,1,0  1,2,1  0,1,0' \
       face_spread_normalize.png

[IM Output]
| !」文字は、さまざまな UNIX コマンドラインシェルで特別な目的に使われることもあります。そのため、引用符内であってもバックスラッシュでこの文字をエスケープしなければならない場合があります。注意が必要です。
---|---
カーネルが正規化されたので、整数を使ってより簡単な方法で定義できることに注意してください。正規化されたカーネルは、前の「スケーリングされた」カーネルと同じになります。通常、常にカーネルを正規化したくなるでしょう。そのため、より簡単な「[-convolve](https://imagemagick.org/command-line-options/#convolve)」バリアントは、この正規化を自動的に行います。カーネルを正規化させた後、さらに指定した量でスケーリングして出力範囲を調整させることもできます。これをさらに簡単にするため、スケーリング係数をパーセントで指定できます。例えば、ここではカーネルを正規化しますが、その後値を算出されたサイズの50%に再スケーリングして、より暗い結果を生成します。 |

  magick face.png -define convolve:scale=50%\! \
         -morphology Convolve  '3x3: 0,1,0  1,2,1  0,1,0' \
         face_spread_norm_half.png

[IM Output]
!」の値を使うことは、実際には「1!」や「100%!」を使うのと同等であることに注意してください。カーネル内の正と負の値を反転したい場合は、負のスケーリング係数を使うこともできます。この例についてはぼかしを使った画像の「アンシャープ」を参照してください。このようにカーネルが正規化された場合、カーネル表示出力は正規化されていることを伝えます。

正規化の仕組み

実際の「カーネル正規化 」の動作は、すべてのカーネル値(可能性のある負の値も含む)を加算することです。結果が非ゼロの場合、すべての値を、それらの合計値が1(「1.0」)になるようスケーリングします。負の値がある場合、これは実際には1より大きい値を持つカーネルを作ることがあり、典型的には原点でそうなることに注意してください。これは特にアンシャープカーネルで起こります。ただし重要な点は、カーネル全体が「1.0」に加算されることであり、それによって畳み込み操作で最終画像が暗くも明るくもならないようにします。加算の結果がゼロ(「0.0」)の場合、カーネルは特別なゼロ和カーネルと見なされます。その場合、カーネルはすべての正の値が「1.0」になるようスケーリングされ、同じ要領で、すべての負の値の合計が「-1.0」になります。これらのカーネルは特にエッジ検出技術で広く見られます。カーネルがこの形であれば、たとえ実際には正規化されたゼロ和カーネルでなくても、カーネル表示出力はそれがゼロ和であることも示します。ただしそれは表示される他の数値からも容易に分かります。数学的に決定されるカーネルのほとんどはあらかじめ正規化されています。これには数学的に導出されるカーネル「[Unity](#unity)」、「[Gaussian](#gaussian)」、「[LoG](#log)」、「[DoG](#dog)」、「[Blur](#blur)」、「[Comet](#comet)」が含まれます。ただし、離散的な定数カーネルはあらかじめ正規化されていないので、上記のカーネル正規化設定を使ってこれを行う必要があります。これには次のカーネルが含まれます:「[Laplacian](#laplacian)」、「[Sobel](#sobel)」、「[Roberts](#roberts)」、「[Prewitt](#prewitt)」、「[Compass](#compass)」、「[Kirsch](#kirsch)」、「[FreiChen](#freichen)」。「[FreiChen](#freichen)」カーネルには、より特定の目的のために特別に事前重み付けされたサブタイプがあることに注意してください。FreiChen カーネルは正規化すべきではなく、そのまま使うべきです。

ゼロ和の正規化

すべての畳み込みカーネルが正の値だけを使うわけではありません。正と負の値が混在するカーネルもあり、そうしたカーネルの値はしばしば合計がゼロになるよう意図され、ゼロ和カーネルを生成します。そのようなカーネルは、より高度な画像畳み込みにとって非常に重要であり、エッジ検出画像のシャープ化の技術を提供します。前節で述べたように、通常の正規化フラグ「!」はそのようなカーネルでも機能します。しかし、特別な状況のために、カーネルが「ゼロ和」のままであることを確実にしたい場合があります。特別な「^」正規化メソッドは、次のような状況でカーネルがゼロ和であることを保証する方法を提供します...

  1. ユーザーのカーネル定義がゼロ和を保証するのに十分な精度がない場合。例えば、「1/3」やその他の3の分数係数を正確な浮動小数点の10進数として指定することはできません。
  2. 数学的曲線がカーネルのサイズ(半径)によって「クリップ」され、もはやゼロ和でなくなる場合。例えば、これは無限応答曲線に基づく「[LoG](#log)」や「[DoG](#dog")」カーネルで起こります。IM は実際、まさにこの理由でこれらのカーネルに対して内部的にこの特別な正規化を使用します。
  3. 相関の「形状マスク」がゼロ和であることを保証し、探索において IM が正と負の一致を均等に探せるようにする場合。下記の相関による形状探索を参照してください。

何が起こるかというと、カーネルのすべての正の値と負の値を別々の実体として正規化します。つまり、すべての負の値が合計「-1.0」になるようスケーリングされ、すべての正の値が合計「+1.0」になるようスケーリングされます。その結果、カーネル全体としては必ず合計がゼロになることが保証されます。「Gaussian」のような全て正のカーネルにこの正規化メソッドを使っても、依然として正しく正規化されたカーネルが得られることに注意してください。そのため、この形の正規化はぼかしカーネルでも使えます。ただし、直接定義されたシャープ化カーネルやアンシャープ化カーネルの正規化には使うべきではありません。これらは負の値を含み得ますが、(通常の正規化メソッドを使って)合計が1の値になる必要があるからです。

恒等カーネルとのブレンド

カーネルスケーリング設定の完全な構文は次のいずれかです...

**-define convolve:scale='{_カーネルスケール_}[!^] [,{_原点加算_}] [%]' -set option:convolve:scale '{_カーネルスケール_}[!^] [,{_原点加算_}] [%%]'**

[-set](https://imagemagick.org/command-line-options/#set)」を使う際はパーセント文字を二重にすることに注意してください。オプションの正規化フラグ「!」または「^」は、(要求された場合)まずユーザー定義または組み込みのカーネルに適用されます。その後、カーネルは「カーネルスケール 」係数でスケーリングされ、結果に対する畳み込みの実効的な「強さ」を増減します。デフォルトのスケーリング係数は「1.0」です。最後に、カーネルの「原点」値に、カンマの後の数値が加算されます。デフォルトの「原点加算 」は「0.0」です。この最後のステップは事実上、先に生成された正規化・スケーリング済みのカーネルに、指定した「スケーリング」の恒等カーネルを「加算」します。これにより次のことができるカーネルが生成されます...

パーセント(「%」)フラグを与えると、そのパーセンテージは「カーネルスケール 」係数と「原点加算 」の両方に適用されることに注意してください。これは分数が関わる場合にスケールを読みやすく理解しやすくします。カーネルスケーリング define の使用例...

  -define convolve:scale='!50%,100%'  -morphology Convolve Laplacian:2

要求された「[Laplacian:2](#laplacian_2)」カーネルを生成します...

0 -1 0
-1 4 -1
0 -1 0

それを正規化します('!' フラグ)

0 -0.25 0
-0.25 1 -0.25
0 -0.25 0

50% でスケーリング

0 -0.125 0
-0.125 0.5 -0.125
0 -0.125 0

恒等カーネルを加算(原点値に100%を加算)

0 -0.125 0
-0.125 1.5 -0.125
0 -0.125 0

そして今や「[Laplacian:2](#laplacian_2)」をシャープ化カーネルとして畳み込みに使えますが、シャープ化の強さは「50%」だけです。スケール設定のどこかに「%」フラグを与えると、両方の値がパーセンテージになることを覚えておいてください。存在しない場合、両方の値は単純な直接の乗数です。例えば、これらのスケーリングオプションはすべて同等です

     50,100%     50%,100    %50,100      .5,1      0.5,1.0

2つの正規化フラグについても同様です。これらはconvolveスケーリング設定のどこに現れてもよいですが、他のスケーリングが行われる前に常に最初に適用されます。

出力結果のバイアス制御

負の値を含むカーネルを扱う場合、結果画像内の一部のピクセルには負の値が割り当てられるべきです。これは特にゼロ和カーネル(下記参照)の場合に当てはまります。残念ながら、生成された負の値を保存するために特別にビルドされたHDRI 版の ImageMagickを持っていない限り、負の結果はゼロ(黒)にクリップされます。畳み込みからは正の結果しか得られません。それは通常の画像フォーマットには保存できず、結果の半分だけが残ります。生成された負の値を保存するためにHDRI 版の ImageMagickをビルドし、その後欲しい情報を抽出することもできます。あるいは、負のスケーリング係数を使ってカーネルを反転することもできます。例えば次のようにします...

-define convolve:scale='-1'

しかしその場合、負の結果だけが得られ、正の結果がクリップされます。ただし、IM の設定「[-bias](https://imagemagick.org/command-line-options/#bias)」を使うことで、正と負の両方の結果を保存できます。非HDRI版の IM で使う設定は次の通りです...

     -define convolve:scale=50%\!  -bias 50%

最初の設定は、出力を通常得られるサイズの半分にスケーリングし(正規化された後)、正と負の両方の結果のための余地を作ります。その後、結果を画像に保存し戻す前に、ピクセル出力に50%グレーを加算します。これらの設定により、いかなる「ゼロ」結果も純粋なグレーになり、負の結果はこれより暗く、正の結果はこれより明るくなります。黒は「-1.0」を、白は「+1.0」を表します。これを行う一例は、下記のCorrelate 形状探索の例で示されています。


画像のぼかし(ローパスフィルタリング)

IM 例の別のセクション、特に画像のぼかしとシャープ化では、実際にこの主題の実用的な側面を扱っています。ここではより具体的な詳細を見ます。ただしまず、基本的なカーネルと、それらを修正せずに直接使う方法を説明します。後ほど、他の効果を生成するためにぼかしを修正する方法を見ます。

ぼかしカーネル

[IM Output]

Unity

これは実際には何もしない特別なカーネルです。1つのカーネル要素だけが指定され、その結果、各ピクセルは変化なくそれ自身に置き換えられます。例えば、これは無操作の畳み込みです...

  magick face.png -morphology Convolve Unity face_unity.png

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

IM v 6.6.9-4 以降、このカーネルは単一の引数を、カーネル固有のスケール引数として取ることができます。これにより、画像の値を乗算して、画像を明るくしたり暗くしたりするのに使えます。 |

  magick face.png -morphology Convolve Unity:0.5 face_dimmed.png

[IM Output]
これはあまり役に立たないように見えるかもしれませんが、柔らかいぼかしアンシャープ効果の生成に、あるいはカーネルスケーリングカーネル恒等ブレンドが使えないマルチカーネルシーケンスで使えます。同じ単一要素カーネルは「[Disk:0.5](morphology.html#disk)」を使っても生成でき、これもカーネル生成の一部として追加のスケーリング引数を指定できます。(例:先の例なら「Disk:0.5,0.5」)。(畳み込み用の)類似のカーネルは、「sigma 」が「0.0」の「[Gaussian](#gaussian)」カーネル生成器でも生成できます。ただしそれは、中心の「1.0」値が8つの「0.0」値に囲まれた小さな3x3カーネルしか生成できません。 [IM Output]

形状カーネルによる平均(Mean/Average)フィルタリング

以下で定義されるほとんどの畳み込みカーネルは一般に何らかの形でガウシアン曲線を使いますが、以前のモルフォロジー形状カーネルの1つを使って、指定された(大きな)領域にわたってピクセルを単純に平均することもできます。もちろん、近傍の単なる和ではなく実際に平均を生成するためには、カーネルを正規化する必要があります。例えば、ここでは小さめの「[Octagon](morphology.html#octagon)」形状カーネルを使い、各ピクセルを取り囲む円形領域内で見つかったすべてのピクセル値を平均します。

  magick face.png -define convolve:scale=! \
         -morphology Convolve Octagon:2 face_mean.png

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

その結果、各ピクセルの値が定義された近傍内の25ピクセルすべてに等しく広がります。つまり、与えられた形状にわたる「平均」または「平均化」フィルタと同等です。その平均から元のピクセルを除外し、周囲のピクセルだけを使いたい場合は、「[Ring](morphology.html#ring)」カーネル(1つの半径だけを与える)を使えます。他の形状カーネルも同じ方法で使え、例えば「[Diamond](morphology.html#diamond)」、「[Square](morphology.html#square)」、あるいは大きな「[Disk](morphology.html#disk)」形状にわたって、好きなサイズでピクセル値を平均できます。ただし、形状領域にわたる一定の平均化は画像をぼかしはしますが、結果画像に異常な効果(特にエイリアシングアーティファクト)を生じる傾向があります。より具体的には、「フラット」な平均化カーネルを使うと、鋭いエッジをより厚い線形の傾斜に変える傾向があり、厚くなったエッジで傾斜が急に変化します。結果の厚さはカーネルの「radius*2-1」です。異なるエッジ角度が傾斜の厚さや傾斜の線形性にどう影響するかは、「フラット」または平均化カーネルの形状に依存します。

  magick -size 80x80 xc: -draw 'polygon 15,15 15,65 60,15' shape.png
  magick shape.png \
         -define convolve:scale=! -morphology Convolve Square:5 \
         shape_mean_square.png
  magick shape.png \
         -define convolve:scale=! -morphology Convolve Disk:5 \
         shape_mean_disk.png

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

上記の対角線のぼかしは、正方カーネルとディスクカーネルで異なることに注意してください。正方の「線形傾斜」ぼかしを生成する別の方法は、特定の半径とともに非常に大きな sigma を使うことです。例えば、上記の正方カーネル畳み込みは -blur 5x65535 を使っても達成できます。これはモルフォロジーが利用可能になる前に、Fred Wienhaus がスクリプトでよく使っていました。 [IM Output]

Gaussian カーネル(2次元ガウシアンぼかし)

お気づきかもしれませんが、「Gaussian」カーネルは画像を畳み込むのに最もよく使われるカーネルです。これはぼかし効果のための数学的に理想的なカーネルです。例えば、これは小さな「Gaussian」カーネルのカーネル表示です(これらは非常に速く非常に大きくなります)...

  magick xc: -define morphology:showKernel=1 \
         -morphology Convolve:0 Gaussian:0x0.8 null:

[IM Text]

上記には実際には畳み込みを適用したくありませんでした。使われるカーネルを示したかっただけだからです。そのため「:0反復回数を使い、何も行わないようにしました。同様に、特別な「[null:](files.html#null)」ファイルフォーマットを使って結果の画像出力を破棄しています。畳み込み出力範囲を見れば分かるように、「Gaussian」カーネルはあらかじめ正規化(スケーリング)されています。ただし、依然としてかなり大きなカーネルであり、小さな分数値で満たされていることにも気づくでしょう。よく見ると、最大値(2.48678、これは1行目にも記載)が中心にあり、エッジや角に向かって最小値(約 .000000194 の値)があることがわかります。これは畳み込みを使った典型的なガウシアンぼかしです...

  magick face.png -morphology Convolve Gaussian:0x2 face_gaussian.png

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

カーネルの構文は分かりやすいものです...

   Gaussian:[{_radius_}]x{_sigma_}

これらの引数は実際、「[-gaussian-blur](https://imagemagick.org/command-line-options/#gaussian-blur)」オペレータが使うものと全く同じで、それは実際このカーネルを使って畳み込みを実行します。最初の数値は、ほとんどのモルフォロジーカーネルと同様、カーネルの「radius 」つまりサイズです。これは単なる整数で、最小値は1であり、最小のカーネルは3x3要素サイズになります。最良の方法は常にゼロを指定することで、これにより ImageMagick が与えられた「sigma 」値に対して適切な半径を算出できます。2番目のより重要な引数は「sigma 」で、各ピクセルがどれだけぼかされる、つまり「広がる」べきかを定義します。値が大きいほど画像はよりぼやけます。これは浮動小数点値です。sigma 値は必ず指定しなければなりません。sigma 値に「0.0」を与えると、(与えられた半径、あるいは半径1で、単一の「1.0」値が「0.0」値に囲まれた3x3カーネルとなる)かなり役に立たない「[Unity](#unity)」カーネルになってしまいます。上で見たように、どんな種類の「[Unity](#unity)」カーネルで畳み込んでも、画像には_何も_しません! 「radius 」を指定する場合は、一般に「sigma 」の少なくとも2倍の大きさにするのが良い考えです。IM は通常、約3倍の半径を算出します(実際には意味のある結果を提供する最大の半径です)。ただしそれは、特定の IM インストールのコンパイル時の品質に依存します。「Gaussian」カーネル引数の効果や、画像のぼかし全般についての詳しい情報は、画像のぼかしを参照してください。 [IM Output]

Blur カーネル(1次元ガウシアンぼかし)

Blur」カーネルはGaussian カーネルに非常によく似ており、同じ引数も取ります(下記参照)。しかし、ガウシアンが2次元曲線であるのに対し、「Blur」カーネルは1次元曲線を生成します。つまり、値の長く細い1行を生成します。これは小さな「Blur」カーネルのカーネル表示出力です。 | |

  magick xc: -define morphology:showKernel=1 \
         -morphology Convolve:0 Blur:0x0.8 null:

[IM Output]
| [IM Text]


上に示したグラフは、デフォルトの「Blur」カーネルの実際のプロファイルです。これはカーネル画像スクリプト「[kernel2image](../static/img/scripts/kernel2image)」を使って作成され、その画像を「[im_profile](../static/img/scripts/im_profile)」スクリプトでグラフ化したものです。このカーネルが表す「ガウシアン釣鐘曲線」がはっきりと示されています。 これは、このカーネルを使って画像を水平方向にぼかす例です。 |

  magick face.png -morphology Convolve Blur:0x4 face_blur.png

[IM Output]
カーネルの構文は「[Gaussian](#gaussian)」とまったく同じですが、追加のオプションの回転角があります。

   Blur:[{_radius_}]x{_sigma_}[,{_angle_}]

先ほどと同様、2番目の値「sigma 」は必須で、ゼロに設定すると「[Unity](#unity)」カーネルの線形版が得られます。 「angle 」によってカーネルを90度回転でき、画像を垂直方向にぼかせます。 |

  magick face.png -morphology Convolve Blur:0x4,90 face_blur_vert.png

[IM Output]
現時点では90度回転のみが可能です。これは ImageMagick の後のバージョンで変わるかもしれません。このカーネルの目的は実際、「[Gaussian](#gaussian)」カーネルが生成する2次元画像ぼかしのより高速な形を作ることです。これがどう行われるかの詳細は、下記のGaussian と Blur カーネルの比較を参照してください。 [IM Output]

Comet カーネル(半1次元ガウシアンぼかし)

Comet」カーネルは「[Blur](#blur)」カーネルとほぼ全く同じですが、実際には半分のぼかしカーネルです。

  magick xc: -define morphology:showKernel=1 \
         -morphology Convolve:0 Comet:0x1.0 null:

[IM Text]

原点の定義位置がカーネルの中心ではなく左端にあることに注目してください。これは畳み込みカーネルとしては非常に珍しく、そのため非常に珍しい結果を生み出します。それは、指で濡れた絵の表面をなすりつけて色の跡を残したかのように、画像を一方向にぼかし広げます。彗星の尾、あるいは流星や流れ星の残した跡のようなものです。 |

  magick face.png -morphology Convolve Comet:0x5 face_comet.png

[IM Output]
前景色と背景色の両方が「なすりつけられた」ことに注意してください。前景色だけをぼかしたい場合は、背景を透明にして、前景をぼかした後に追加してください。3番目の_angle_ 引数を与えて、カーネルをその「原点」を中心に90度の任意の倍数で回転することもできます。 |

  magick face.png -morphology Convolve comet:0x5+90 face_comet_vert.png

[IM Output]
このカーネルは実際、特化したモーションブラーオペレータが使うのと同じカーネルですが、そのオペレータはぼかしを任意の角度で機能させるために、非常に手の込んだ座標ルックアップ処理も行います。ただしそれはうまくいかず、45度のような大きな角度では色の「塊」を生じます。願わくは、90度刻み以外の角度でより良いモーションブラー型効果を作るために、適切なカーネル回転が実装されることでしょう。[IM Output]

Gaussian と Blur カーネルの比較

述べたように、「[Gaussian](#gaussian)」と「[Blur](#blur)」カーネルは非常に密接に関連しており、実際同じ仕事ができます。両方ともガウシアン曲線の表現であり、一方は2次元表現、もう一方は1次元表現です。例えば、これは「-morphology Convolve Gaussian:0x2」操作と同等の「-gaussian-blur 0x2」の繰り返しです。 |

  magick face.png -gaussian-blur 0x2 face_gaussian-blur.png

[IM Output]
これは、互いに90度回転させた2つの別々の線形(1次元)ぼかし操作を使うことで置き換えられます(順序も実際には問題になりません)... |

  magick face.png -morphology Convolve Blur:0x2 \
         -morphology Convolve Blur:0x2+90 face_blur_x2.png

[IM Output]
2つの別々の畳み込みを指定するのではなく、両方のカーネルをカーネルリストとして与えることもできます。例えば

  magick face.png -morphology Convolve 'Blur:0x2;Blur:0x2+90' face_blur_x2.png

IM はデフォルトで、マルチカーネル合成設定で定義された通り、最初のconvolveカーネルの結果を2番目(およびそれ以降)のconvolveカーネルで「再反復」します。一覧の90度回転(回転カーネルリスト)に1つのカーネルを展開するよう IM に頼むことで、上記をさらに簡略化することさえできます。「>」を使って90度回転のリスト(この場合は2つのカーネル)を行います。例えば...

  magick face.png -morphology Convolve 'Blur:0x2>' face_blur_x2.png

上記の例はすべて互いに同等であり、これが「[-blur](https://imagemagick.org/command-line-options/#blur)」オペレータの動作の仕方です。 |

  magick face.png -blur 0x2 face_blurred.png

[IM Output]
これが「[-blur](https://imagemagick.org/command-line-options/#blur)」と「[-gaussian-blur](https://imagemagick.org/command-line-options/#gaussian-blur)」オペレータの本当の違いを表しています。後者は1つの大きな2次元カーネルを使い、前者は2つの小さな1次元カーネルを使います。ただし速度の面では、「[-blur](https://imagemagick.org/command-line-options/#blur)」オペレータは通常、桁違いに高速です。1つの非常に大きなカーネルではなく、2つのはるかに小さなカーネルを使うからです。ぼかし引数(sigma 引数のサイズ)が大きいほどカーネルが大きくなり、2つの操作間の速度差も大きくなります。そのため、「[-blur](https://imagemagick.org/command-line-options/#blur)」オペレータが一般に推奨されます。2つのオペレータ間の結果の違いは、わずかな量子丸め効果(HDRIを使っていない場合)とエッジ効果(仮想ピクセル設定に依存)だけです。どちらも、「blur」畳み込みの2つの別々のパスの間で中間画像を保存することで生じる情報の損失によって引き起こされます。この違いは典型的には非常に小さく目に見えず、いかなる実用上も問題になりません。

柔らかいぼかし(元画像とのブレンド)

どんな種類のぼかしも、元画像の一部とブレンドすることでその影響を和らげることができます。特に非常に強いぼかしを適用する場合です。例えば...

  magick face.png -morphology Convolve Gaussian:0x3 face_strong_blur.png
  magick face.png face_strong_blur.png \
         -compose Blend -define compose:args=60,40% -composite \
         face_soft_blur.png

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

これは「[Blend](compose.html#blend)」合成メソッドを使い、ぼかした画像(合成のソース画像)の「60%」と元画像(合成のデスティネーション画像)の「40%」を混ぜて、最終画像に「柔らかいぼかし」効果を与えました。ただし、同じ比率を使って恒等カーネルとのカーネルのブレンドによって、同じことを直接行うこともできます。 |

  magick face.png -define convolve:scale=60,40% \
         -morphology Convolve 'Gaussian:0x3' face_soft_blur2.png

[IM Output]
スケーリング数値の順序は同じであることに注意してください。最初の数値(「60%」)は与えられたカーネルをスケーリングして出力への影響を減らし、2番目の数値(「40%」)は結果が暗くならないよう「[Unity](#unity)」(つまり「恒等」)カーネルを十分に加算します。重要な点は、ぼかしカーネルでは、合成ブレンドの場合と同じように、2つの数値の合計が「100%」になることです。より高速な2パスぼかしも使えますが、この場合「Blend」をカーネルに直接組み込むことはできません。2つの別々の畳み込みがきれいに「分離」しないからです。そのため、後でブレンド合成を再び行う必要があります。 |

  magick face.png \( +clone -blur 0x3 \) \
         -compose Blend -define compose:args=60 -composite \
         face_soft_blur3.png

[IM Output]
元画像とブレンドしたいぼかした(ソース)画像の量だけを与えればよいことに注意してください。そのため「100」の値はぼかした画像を、「0」は元画像を与えます。 | [-blur](https://imagemagick.org/command-line-options/#blur)」オペレータは、より高速な2パスぼかしカーネルを使うのと正確に同等であることを覚えておいてください。
---|---

ぼかしを使った画像の「アンシャープ」(元画像からの減算)

このカーネルのブレンドをさらに進めて、負のスケーリングを使い始めると、元画像からぼかし効果を減算できます。その結果が「アンシャープ(unsharp)」と呼ばれる技術です。なぜこのような残念な名前が付いたのかについては、Unsharp, Wikipedia を参照してください。 |

  magick face.png -define convolve:scale=-100,200% \
         -morphology Convolve 'Gaussian:0x2' face_unsharp.png

[IM Output]
負のカーネルスケーリング係数が使われていても、2つの数値は依然として上記とまったく同じように合計が「100%」になることに注意してください。これは合成ブレンドでも行えます。上記の例は、実際には名前を誤った「[-sharpen](https://imagemagick.org/command-line-options/#sharpen)」オペレータの動作とまさに同じですが、「sigma 」のぼかし制御だけがあります。ただし、操作の他の制御は提供されません。ブレンドはまさに上記の通りです。より高速な2パスの1次元ぼかしカーネルを使えますが、この場合もブレンド操作を別ステップとして行う必要があります。 |

  magick face.png \( +clone -blur 0x2 \) \
         -compose Blend -define compose:args=-100,200 -composite \
         face_unsharp_fast.png

[IM Output]
お気づきかもしれませんが、これは柔らかいぼかしとほぼ同じですが、ぼかした画像が元画像に加算されるのではなく減算される点が異なります。これは外挿ブレンド、つまり通常の0から100パーセントの範囲を超えたブレンドとして知られるブレンドメソッドです。先ほどと同様、元画像から減算したいぼかした画像の量を単純に指定できます。例えば、画像のアンシャープ化をやり過ぎて、いくらかのエイリアシングと色の歪みを引き起こしてみましょう。 |

  magick face.png \( +clone -blur 0x2 \) \
         -compose Blend -define compose:args=-200 -composite \
         face_unsharp_200.png

[IM Output]
完全な「[-unsharp](https://imagemagick.org/command-line-options/#unsharp)」オペレータは、別の種類の制御を提供します。具体的には差分しきい値で、与えられた差分が、画像内の実際のエッジ付近のように大きい場合にのみシャープ化が適用されます。そのしきい値を使えば、しわやカメラノイズのような小さな欠陥を「シャープ化」するのを防げます。画像のアンシャープ化は典型的に、リサイズや変形の後に非常に小さなぼかし(sigma=0.75 程度)で使われ、最終結果を改善します。この例についてはリサイズした画像のシャープ化を参照してください。画像シャープ化に「アンシャープ」技術を使う代わりに、実際に画像のエッジを見つけてそれを使って画像をシャープ化することもできます。詳細は下記のエッジ検出による画像のシャープ化を参照してください。ただし、それは一般に遅いと見なされますが、実際にはそれほどでもありません。


エッジ検出畳み込み(ハイパスフィルタリング)

エッジ検出は、畳み込みが多用されるもう1つの分野です。ここでの課題は、画像のエッジをさまざまな方法で強調または強化することです。これは、エッジをできるだけ正確に特定するため、または各エッジの傾斜の角度や方向を判定するためです。ただし、この仕事は、スキャナ、デジタルカメラ、あるいは JPEG 画像ファイルフォーマットの非可逆圧縮によって生じるノイズが画像に存在することで、はるかに難しくなります。一般に、より大きなカーネルはノイズをよりよく処理しますが、エッジを適切に局所化する点で劣ります。一方、より小さなカーネルは鋭いエッジ位置の結果を生成しますが、画像内のノイズによる誤った結果が増えます。エッジ検出のために開発・研究されてきた、小さくよく知られたカーネルが多数あります。これらのほとんどは、その数学を研究した、あるいはその特定のカーネルタイプを開発した数学者にちなんで「名付けられて」います。そのため、「[Laplacian](#laplacian)」、「[Sobel](#sobel)」、「[Prewitt](#prewitt)」といったカーネルがあります。これらの「名前付き」カーネルは一般に非常に小さく、整数を使って定義されているので、速度のために特別に設計された最適化されたソフトウェアやハードウェアに組み込めます。つまり、これらは「離散」カーネルと言われます。そのため、使用の一部としてカーネルをスケーリングまたは正規化する必要があります。エッジ検出には、画像のエッジをシャープ化する方法を提供するという副次的な効果もあります。

ゼロ和カーネル

すべてのエッジ検出カーネルには1つの共通する特徴があります。それらはすべてゼロ和です。つまり、負の値を含みますが、カーネル内のすべての値の合計はゼロになります。滑らかでフラットな色の画像に対しては、そのようなカーネルを使った畳み込みは「ゼロ」つまり黒い画像を生成します。しかし、その他の画像に対しては、負と正の両方の値を含む結果になります。例えば、ここではいくつかの基本図形を含む画像に、離散的な「[Sobel](#sobel)」エッジ検出器を適用します...

  magick -size 80x80 xc:black \
         -fill white -draw 'rectangle 15,15 65,65' \
         -fill black -draw 'circle 40,40 40,20' shapes.gif
  magick shapes.gif -define convolve:scale='!' \
         -morphology Convolve Sobel shapes_sobel.gif

[IM Output] [IM Output]

結果を見ると、カーネルが方向性を持っており、(ゼロ角度の「[Sobel](#sobel)」カーネルで定義された通り)垂直なエッジだけが見つかっていることがわかります。しかし、それは1組のエッジ、つまり「正の」左から右への黒から白への傾斜だけを見つけました。「負の」傾斜を得るには、カーネルスケーリング設定を使ってカーネルを反転する必要があります。例えば... |

  magick shapes.gif -define convolve:scale='-1!' \
         -morphology Convolve Sobel shapes_sobel_neg.gif

[IM Output]
[Sobel](#sobel)」カーネルでは、180度回転させても「スケール反転」と同じ結果が得られますが、すべてのカーネルがこのように対称なわけではありません。もう1つの解決策は、結果に出力バイアスを加えることです。つまり、結果画像に50%グレーを加えて、負の値がこれより暗く、正の値がこれより明るくなるようにします。ただし、結果が画像の「黒」と「白」の限界によって「クリップ」されないよう、カーネルをスケーリングする必要もあります。 |

  magick shapes.gif -define convolve:scale='50%!' -bias 50% \
         -morphology Convolve Sobel shapes_sobel_bias.gif

[IM Output]
極性を気にしないなら、少しの工夫で結果の絶対値を得られます.. |

  magick shapes.gif -define convolve:scale='50%!' -bias 50% \
         -morphology Convolve Sobel -solarize 50% -level 50,0% \
         shapes_sobel_abs.gif

[IM Output]
方向判定を含むより多くの結果処理技術については、「[Sobel](#sobel)」カーネルを参照してください。出力バイアスを使う代わりのもう1つの方法は、ImageMagick の特別なHDRI版をビルドすることです。これは浮動小数点値を使ってメモリ内に画像を保存し、画像の値が整数の使用によって「クリップ」されたり「丸められ」たりしないことを意味します。ただし、この特別な版の IM を使っても、通常の画像ファイルフォーマットに保存する前に結果を後処理する必要があるか、特別な浮動小数点対応の画像ファイルフォーマットを使う必要があります。しかし、中間画像の結果でクリッピングや丸め効果を心配する必要はなく、扱いやすくなります。

エッジ検出カーネル

[IM Output]

LoG: ガウシアンのラプラシアン

   LoG:{_radius_},{_sigma_}

LoG」つまり「Laplacian of a Gaussian(ガウシアンのラプラシアン)」は、得られる最良のエッジ検出カーネルの1つです。「メキシカンハット」カーネルとしても知られています。基本的には「[Laplacian](#laplacian)」微分(傾き)オペレータで、ガウシアンぼかしの追加によって平滑化されたものです。これによって画像内のノイズの影響のほとんどが除去され、それは「sigma 」設定で調整できます。カーネルには、強い中心ピークの周りにリングを形成する負の値が含まれます。上に示した「カーネル画像」では、負の値が暗い(ほぼ黒い)色として示され、エッジに向かってゼロ(暗いグレー)へと減衰していきます。そしてこれがその効果です..画像のエッジをどう強調するかを示しています。

  magick face.png -bias 50% -morphology Convolve LoG:0x2 face_log.png

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

ラプラシアンカーネルは無方向ですが、エッジの両側に正と負の両方の値の尾根を生成します。エッジを特定するには、正と負の尾根の間の、ゼロ交差の点を探します。これはMarr-Hildreth エッジ検出として知られる技術です。このカーネルは画像のシャープ化にも理想的です。
[IM Output]

DoG: ガウシアンの差分

   DoG:{_radius_},{_sigma1_}[,{_sigma2_}]

これは「DoG」つまり「Difference of Gaussians(ガウシアンの差分)」カーネルを生成します。「sigma1 」によって生成されたガウシアンから「sigma2 」によって生成されたガウシアンが減算されます。通常「sigma2 」が大きい方で、カーネルの「中心ピーク」が正になるようにします。2つの数値を逆にすると、結果のカーネルが事実上反転されます。ガウシアンのラプラシアンに対する大きな批判の1つは、そのような珍しい数学的曲線であるため実装が難しいことです。また、あまりよく文書化されていない曲線でもあります。もう1つの側面は、ガウシアンでできるような、より高速な2パスの解に「分離」できないことです(Gaussian と Blur カーネルの比較を参照)。しかし、わずかに異なる sigma 値(約1.6の比率)を持つ2つの「[Gaussian](#gaussian)」カーネルを生成し、それらを互いに減算することで、ガウシアンのラプラシアンの近似を実際に生成できます。その結果、「[DoG](#dog)」は「[LoG](#log)」カーネルよりもハードウェアではるかに簡単に生成できます。例えば、ここでは「[LoG](#log)」と「[DoG](#dog)」カーネルのカーネル画像を並べて比較しています。

[IM Output] [IM Output]

Difference of Gaussian, Wikipedia のウェブページを見ると、「[LoG](#log)」(つまり「メキシカンハット」)のプロファイルと「[DoG](#dog)」を比較したグラフがあり、一致する曲線の間の非常にわずかな違いを示しています。LoG の sigma をほぼ同等の「DoG」を生成するようにどうマップするかについて、より多くの情報が欲しいです。ご存知の方はフッターのアドレスまでメールでお知らせください。 適用された結果も非常によく似ています。 |

  magick face.png -bias 50% -morphology Convolve DoG:0,1.8,2.4 face_dog.png

[IM Output]
両方の「sigma 」値を定義すべきで、少なくとも1つは非ゼロであるべきことに注意してください。sigma 成分のいずれかにゼロ値を与えると、「[Unity](#unity)」カーネルと同等になり、画像を変化させずに保つことを意味します。両方の値がゼロの場合、2つのガウシアンは「[Unity](#unity)」カーネルとなり、減算すると完全にゼロまたは黒の結果(プラス任意のバイアス値)を生成します。引数が「Dog:0,0,_非ゼロ_」の場合、DoG は単純なハイパスフィルタになります。これは「Unity」カーネル(元画像を生成)からローパスフィルタカーネル(ぼかした画像)を減算したものと定義されます。この場合 sigma1=0 は単なる「Unity」カーネルで、sigma2=非ゼロ はガウシアンローパス(ぼかし)フィルタカーネルです。したがって、以下は sigma2=2 のフィルタ値を持つハイパスフィルタリングされた画像を生成します |

  magick face.png -bias 50% -morphology Convolve DoG:0,0,2 face_dog_unity.png

[IM Output]
radius=2 のフィルタ値を持つ Photoshop のハイパスフィルタは同じ結果を生成します。「DoG:0,2,0」を使うと、基本的に前の画像の(出力バイアスを中心とした)反転版である画像を返すことに注意してください。この技術は、3x3の「等方性ラプラシアン」カーネル、つまり対角方向に不均等なバイアスを持つのではなく、すべての方向で等しい結果を生成する「[Laplacian](#laplacian)」カーネルを生成するのにも使えます。例えば、radius=1(3x3カーネル用)と sigma=1 は次を生成します... | |

  magick face.png -define morphology:showKernel=1 -bias 50% \
          -morphology Convolve DoG:1,0,1 face_laplacian_isotropic.png

[IM Text]
| [IM Text]


「ガウシアンの差分」を使うことについてのもう1つの点は、はるかに高速な「[-blur](https://imagemagick.org/command-line-options/#blur)」オペレータ(内部で「[Blur](#blur)」カーネルを使う)を使って、同じ結果を生成できることです。ただし、これを行うには2つの「ぼかした」画像をそれぞれ別々に生成し、その後、適切なスケーリングとバイアスを加えて結果を減算する必要があります。例えば... |

  magick face.png \
         \( -clone 0 -blur 0x1.8 \) \( -clone 0 -blur 0x2.4 \) -delete 0 \
         -compose Mathematics -define compose:args=0,-4,4,0.5 -composite \
         face_diff_of_blurs.png

[IM Output]
上記は、非HDRI版の IM で画像の減算中の「クリッピング」の問題を回避するため、特別な数学合成メソッドを使っています。詳細はバイアスのかかったグラデーションの加算を参照してください。唯一の他の要因は、減算中により大きなスケーリング係数を使うこと(数学合成引数の2つの「4」)です。これは、2つの正規化されたぼかしを減算しても、「[DoG](#dog)」カーネルで2つの減算されたガウシアン曲線を一緒に正規化したときに得られるのと同じ(増加した)大きさの結果が生成されないからです。しかし、大きさを除けば、上記の例の画像は最初の「[DoG](#dog)」カーネルの結果と同等で、ただ生成が高速、特に大きな sigma 値で高速です。そしてそれが要点です。より手間がかかるとはいえ、その複雑なメソッドは「[DoG](#dog)」や「[LoG](#log)」カーネルを直接使うよりも高速なのです。

離散 Laplacian カーネル

   Laplacian:{_type_}

多くの科学研究論文で発表されてきた、小さな「Laplacian カーネル」には多くの形があります。ここでは、学術文献で見つけることができたより一般的なものの組み込み版を提供します。これらのカーネルは基本的に「[LoG](#log)」カーネルを使って計算されますが、小さなカーネル配列内で離散的な整数値を使うようスケーリングされています。これにより、整数演算だけを使って画像データを処理する、生成された専用の高速画像フィルタを使えます。ただし、ImageMagick はより汎用的な画像処理器であり、そのような超高速の専用フィルタを提供しません。しかし、これらは理解しやすいので人々が使いたがり、多くが IM に組み込まれています。ここで提供されるカーネルはどれも回転可能ではなく、ほとんどが「異方性」、つまり完全な円形ではなく、特に対角方向でそうです。ただし、真の「等方性3x3ラプラシアンカーネル」を生成する方法については、前節(「[DoG](#dog)」カーネル)を参照してください。最初の2つ「Laplacian:0」と「Laplacian:1」カーネルは、使用される「離散ラプラシアンカーネル」の最も一般的な形です。これらは非常に小さく、エッジを非常に正確に特定しますが、画像ノイズを強調しやすくもあります。すべての「type 」番号が定義されているわけではなく、将来より多くの離散カーネルが定義されるための空きが残されていることに注意してください。使われた番号は、その番号で定義されるカーネルにより合致するよう選ばれました。

Laplacian:0(デフォルト)

8近傍ラプラシアン。おそらく最も一般的な離散ラプラシアンエッジ検出カーネルです。ここではカーネル表示を使って「離散」かつ「非正規化」のカーネルを抽出し、その後出力バイアス付きの正規化されたカーネルの結果を示します。 | |

  magick xc: -define morphology:showKernel=1 -precision 2 \
         -morphology Convolve:0 Laplacian:0 null:
  magick face.png -define convolve:scale='!' -bias 50% \
         -morphology Convolve Laplacian:0 face_laplacian_0.png

[IM Text]
| [IM Text]


ラプラシアンは、それが離散ラプラシアン(直前の例のように)であれ、生成された「[LoG](#log)」や「[DoG](#dog)」であれ、望ましいよりも複雑な結果を生成することがあります。そのような場合、(いかなる出力バイアスもなしに)バイアスのない画像を生成する方がうまくいきます。そこで、より明るい「正の」エッジだけを残すよう、バイアスなしで上記を繰り返してみましょう。 |

  magick face.png -define convolve:scale='!' \
         -morphology Convolve Laplacian:0 \
         -auto-level face_laplacian_positives.png

[IM Output]
この場合、明るい(白い)色の上に暗い(黒い)線があります。これが次にフィルタにエッジを「二重化」させ、示された結果に見られます。この画像では、負のスケーリング係数を使うこと(正のエッジではなく負のエッジを残す)が、テスト画像でうまくいくようでした。 |

  magick face.png -define convolve:scale='-1!' \
         -morphology Convolve Laplacian:0 \
         -auto-level face_laplacian_negatives.png

[IM Output]
ご覧の通り、この画像では負のサイズを使うと、正の結果が生成した「双子化」効果なしに、より強いエッジが生成されます。これは、使われている画像で白い背景に「黒い」エッジ線が使われているためです。余談: 黄色い星の周りに青いエッジが出る理由は、「黄色い」星と「白い」背景の差が青色の減算だからです。背景が黒だったら、黄色のエッジ色が得られたでしょう。

Laplacian:1

4近傍ラプラシアン。これも非常によく使われます。 | |

  magick xc: -define morphology:showKernel=1 -precision 2 \
         -morphology Convolve:0 Laplacian:1 null:
  magick face.png -define convolve:scale='!' -bias 50% \
         -morphology Convolve Laplacian:1 face_laplacian_1.png

[IM Text]
| [IM Text]


結果はそれほど強くありませんが、8近傍ラプラシアンよりも明瞭なことが多いです。

Laplacian:2

3x3 ラプラシアン、中心:4 エッジ:1 角:-2 | |

  magick xc: -define morphology:showKernel=1 -precision 2 \
        -morphology Convolve:0 Laplacian:2 null:
  magick face.png -define convolve:scale='!' -bias 50% \
         -morphology Convolve Laplacian:2 face_laplacian_2.png

[IM Text]
| [IM Text]


Laplacian:3

3x3 ラプラシアン、中心:4 エッジ:-2 角:1 | |

  magick xc: -define morphology:showKernel=1 -precision 2 \
             -morphology Convolve:0 Laplacian:3 null:
  magick face.png -define convolve:scale='400%!' -bias 50% \
         -morphology Convolve Laplacian:3  face_laplacian_3.png

[IM Text]
| [IM Text]


このカーネルは対角エッジを強調し、垂直および水平エッジを消す傾向があります。ただし、何らかの結果を見えるようにするには、(上で行ったように)結果をスケーリングする必要があるかもしれません。

Laplacian:5

5x5 ラプラシアン | |

  magick xc: -define morphology:showKernel=1 -precision 2 \
         -morphology Convolve:0 Laplacian:5 null:
  magick face.png -define convolve:scale='!' -bias 50% \
         -morphology Convolve Laplacian:5 face_laplacian_5.png

[IM Text]
| [IM Text]


ラプラシアンカーネルの経験則は、大きいほど結果がきれいになることで、特にエラーが関わる場合にそうです。ただし、ディテールも少なくなります。

Laplacian:7

7x7 ラプラシアン | |

  magick xc: -define morphology:showKernel=1 -precision 2 \
         -morphology Convolve:0 Laplacian:7 null:
  magick face.png -define convolve:scale='!' -bias 50% \
         -morphology Convolve Laplacian:7 face_laplacian_7.png

[IM Text]
| [IM Text]


Laplacian:15

離散 5x5 LoG(Sigma 約 1.4) | |

  magick xc: -define morphology:showKernel=1 -precision 2 \
         -morphology Convolve:0 Laplacian:15 null:
  magick face.png -define convolve:scale='!' -bias 50% \
         -morphology Convolve Laplacian:15 face_laplacian_15.png

[IM Text]
| [IM Text]


Laplacian:19

離散 9x9 LoG(Sigma 約 1.4) | |

  magick xc: -define morphology:showKernel=1 -precision 2 \
         -morphology Convolve:0 Laplacian:19 null:
  magick face.png -define convolve:scale='!' -bias 50% \
         -morphology Convolve Laplacian:19 face_laplacian_19.png

[IM Text]
| [IM Text]


エッジ検出による画像のシャープ化(元画像のエッジを強調)

[LoG](#log)」と「[DoG](#dog)」カーネルは、ぼかしを使った画像のアンシャープ化とは対照的に、画像のシャープ化にも使えます。基本的に必要なのは、カーネルの結果(負の結果も含む)を元画像に加算することだけです。これを行うのは簡単で、スケーリング係数に100%の重みの「[Unity](#unity)」つまり「恒等」カーネルを加算するだけです。これがそれが提供された理由です。 例えば... |

  magick face.png -define convolve:scale='100,100%' \
         -morphology Convolve 'Log:0x2' face_sharpen.png

[IM Output]
これはアンシャープ技術が生成したもの(右に結果を表示)よりも、はるかに広く滑らかな画像のシャープ化です。つまり、それはぼかしの減算で偽装されたものではなく、実際の真の画像のシャープ化だからです。 | [IM Output]
---|---
先ほどと同様、単一パスの畳み込みだけを実行する場合は、ブレンドカーネルを直接利用できます。例えば、より弱いシャープ化... |

  magick face.png -define convolve:scale='50,100%' \
         -morphology Convolve 'Log:0x2' face_sharpen_50.png

[IM Output]
あるいは、より強いシャープ化... |

  magick face.png -define convolve:scale='150,100%' \
         -morphology Convolve 'Log:0x2' face_sharpen_150.png

[IM Output]
ガウシアンの差分の2パスメソッドを使ってより高速な多段階シャープ化操作を生成できますが、上で示したように、そのような方式は同じ結果を達成するのに4つの畳み込みと別々のブレンド操作を必要とします。FUTURE: これの例を追加 この複雑さが、画像のシャープ化にアンシャープを使う方がより頻繁に好まれる理由です。しかしご覧の通り、重いシャープ化処理には、アンシャープシャープ化よりも適切なシャープ化カーネルを使う方が好ましいです。ただし、リサイズした画像のシャープ化のような軽いシャープ化には、アンシャープを使っても問題ありません。


方向性畳み込み(傾き、コンパス)

上記と同様、これらのカーネルは画像の色強度の傾きを探しますが、任意の傾きではなく、特定の方向の傾きを探します。数学的にはこれは「微分」として知られ、それは実際には単に「傾き」を言うしゃれた言い方です。しかし、異なる方向の傾き情報を知ることは、傾きや画像エッジの角度や「コンパス」方向を判定する手段としても役立ちます。つまり、ある特定の点での画像内の傾きの2次元方向です。傾きは、画像の「エンボス」や「シェーディング」として知られる画像処理技術にも使われます。現時点では「生成された」カーネルは利用できず、SobelRobertsのような「名前付き」の事前定義カーネルだけです。しかし、エンボスやシェーディングのカーネル生成関数は、いずれモルフォロジー/畳み込みカーネルセットに移されるだろうと私は確信しています。それでは、「名前付き」方向性カーネルのいくつかを見てみましょう。

方向性カーネル

Sobel

   Sobel:{_angle_}

[IM Text]

Sobel 」カーネルは、すでにゼロ和カーネルの議論で上で見ました。このカーネルは、特定の直交方向のエッジの傾きを返すよう設計された生の方向性(1次微分)カーネルです。デフォルトでは、「convolve」操作を使って左から右への傾き検出用に設計されています。結果は本質的に画像のX微分(傾き)です。

  magick -size 60x60 xc:black xc:white +append slope_positive.gif
  magick slope_positive.gif -morphology Convolve Sobel slope_sobel.gif

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

| _カーネルを見ると、逆向きに宣言されていると思うかもしれません。ある意味、それは実際に正しいのです。しかしこれは「Convolve」が実際に動作する仕方によるものです。

この「反転」については、下記のConvolve と Correlate の比較でより詳しく知ることができます。

_
---|---
このカーネルは「負の傾き」の指示も生成できますが、これはこのconvolve操作で「50%」のバイアスも使わない限り見えないことに注意してください。前の例には負の傾きはありませんが、この次の例には1つあるので、それが見えるようにバイアス設定も加えました。

  magick -size 40x60 xc:black xc:white xc:black +append slope_both.gif
  magick slope_both.gif -define convolve:scale='50%!' -bias 50% \
         -morphology Convolve Sobel slope_sobel_bias.gif

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

| _このカーネルを「Correlate」で使うと、カーネルが定義された方法に「一致する」傾きが見つかります。その場合、左側が高い(白い値)で右側が低い(黒い値)傾きに対して正の結果が得られます。先の例では2本の線が入れ替わるでしょう。

しかし上記は「Correlation」(カーネルに一致)ではなく「Convolution」です。繰り返しますが、違いの詳細はConvolve と Correlate の比較を参照してください。_
---|---
ご覧の通り、黒から白への傾きを上っていくと白い線(正の傾き)が、白から黒へ下っていくと黒い線(負の傾き)が得られます。これは顔画像にデフォルトの「Sobel」カーネルを使った結果です。

  magick face.png -define convolve:scale='50%!' -bias 50% \
         -morphology Convolve Sobel face_sobel.png

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

sobel やその他のほとんどのエッジ検出カーネルは、非常に強いエッジに沿って2ピクセル幅の応答を、単一ピクセル幅の線に対して3ピクセルの応答を生成する傾向があることに注意してください。これはラプラシアンエッジ検出器よりもはるかに強いです。「angle 」引数を使って、一般に90度の倍数でこのカーネルを回転できます。ただし、設計されていなくても45度の倍数で回転することもできます。これは、45度量子化された方向性微分や、すべての45度回転微分結果の最大値から勾配の大きさを得るのに役立ちます。 これがもう一度、ただし90度回転(上から下)させたものです。 |

  magick face.png -define convolve:scale='50%!' -bias 50% \
         -morphology Convolve Sobel:90 face_sobel_90.png

[IM Output]

[Sobel](#sobel)」カーネルを使って画像のすべてのエッジを集める1つの方法は、カーネルを全方向に4回適用し、見られた最大値を集めること(明るくする数学合成を使う)です。これは勾配の大きさの近似です。 |

   magick face.png -define convolve:scale='!' \
          \( -clone 0 -morphology Convolve Sobel:0 \) \
          \( -clone 0 -morphology Convolve Sobel:90 \) \
          \( -clone 0 -morphology Convolve Sobel:180 \) \
          \( -clone 0 -morphology Convolve Sobel:270 \) \
          -delete 0 -background Black -compose Lighten -flatten \
          face_sobel_maximum.png

[IM Output]
IM モルフォロジーのマルチカーネル処理機能を利用して、上記を簡略化できます。つまり、「[Sobel](#sobel)」カーネルのすべての90度回転の回転リストを作れます。 |

   magick face.png -define convolve:scale='!' \
          -define morphology:compose=Lighten \
          -morphology Convolve 'Sobel:>' face_sobel_maximum_2.png

[IM Output]
上記が何をしているかを正確に見たい場合は、カーネル表示設定と詳細表示設定を加えてください。勾配の大きさを生成するより効率的な技術は、180度回転が単にカーネルを反転するのと同じ結果を生成し、したがって結果を反転するという事実を使うことです。そのため、X と Y の微分(90度回転した畳み込み)を、畳み込みの絶対値を得るための少しの工夫とともに使えば、より少ない処理でそのような結果を達成できます。 |

   magick face.png -define convolve:scale='50%!' -bias 50% \
          \( -clone 0 -morphology Convolve Sobel:0 \) \
          \( -clone 0 -morphology Convolve Sobel:90 \) \
          -delete 0 -solarize 50% -level 50,0% \
          -compose Lighten -composite face_sobel_maximum_3.png

[IM Output]
これは典型的にほとんどの目的に十分です。すべての傾きのより正確な大きさは、(ピタゴラスの定理に従って)2つの X と Y の微分のベクトル加算を行うことで抽出できます。 |

   magick face.png -define convolve:scale='50%!' -bias 50% \
          \( -clone 0 -morphology Convolve Sobel:0 \) \
          \( -clone 0 -morphology Convolve Sobel:90 \) \
          -delete 0 -solarize 50% -level 50,0% \
          +level 0,70% -gamma 0.5 -compose plus -composite -gamma 2 \
          -auto-level face_sobel_magnitude.png

[IM Output]
| _上記の「[-gamma](https://imagemagick.org/command-line-options/#gamma)」関数は、「[Sobel](#sobel)」結果が返す値の数学的な「2乗」と「平方根」を実行するために使われています。詳細はべき乗数学関数を参照してください。

追加の「[+level](https://imagemagick.org/command-line-options/#level)」は、Plus 合成が画像の量子範囲をオーバーフローしないことを保証します。詳細は量子効果、非HDRI vs HDRIを参照してください。_
---|---
大きさの代わりに、2つのエッジ検出結果から傾きの方向を抽出できます。

  magick -size 30x600 xc:'#0F0' -colorspace HSB \
         gradient: -compose CopyRed -composite \
         -colorspace RGB -rotate 90  rainbow.jpg
  magick shapes.gif -define convolve:scale='50%!' -bias 50% \
         \( -clone 0 -morphology Convolve Sobel:0 \) \
         \( -clone 0 -morphology Convolve Sobel:90 \) \
         -delete 0 \
         \( -clone 0,1 -fx '0.5+atan2(v-0.5,0.5-u)/pi/2' rainbow.jpg -clut \) \
         \( -clone 0,1 -fx 'u>0.48&&u<0.52&&v>0.48&&v<0.52 ? 0.0 : 1.0' \) \
         -delete 0,1 -alpha off -compose CopyOpacity -composite \
         face_sobel_direction.png

[IM Output] [IM Output]

最初の「[-fx](https://imagemagick.org/command-line-options/#fx)」式は、「atan()」関数を使って X,Y ベクトルを角度に変換するものです。これは次に、外部の虹色グラデーション画像カラールックアップテーブルとして使って着色されます。2番目の「[-fx](https://imagemagick.org/command-line-options/#fx)」式は、傾きのない領域を透明にするためのしきい値処理された透明度マスクを作成します。ただし、上記の技術は傾きの大きさを考慮しないため、実画像では膨大な量の情報の混乱を生じる傾向があります。これがもう1つの、より複雑なバージョンです。これは計算のほぼすべてを緑「G」チャンネルで行い、必要な画像処理の量を3分の1に減らします。その後、HSB 色空間を使って方向(色相)と大きさ(明るさ)を作成します。 |

  magick face.png -colorspace Gray    -channel G \
         -define convolve:scale='50%!' -bias 50% \
         \( -clone 0 -morphology Convolve Sobel:0 \) \
         \( -clone 0 -morphology Convolve Sobel:90 \) \
         -delete 0 \
         \( -clone 0,1 -fx '0.5 + atan2(v-0.5,0.5-u)/pi/2' \) \
         \( -clone 0   -fill white -colorize 100% \) \
         \( -clone 0,1 -fx 'hypot(u-0.5,v-0.5)*2' \) \
         -delete 0,1 -separate +channel \
         -set colorspace HSB -combine -colorspace RGB \
         face_sobel_magnitude_n_direction.png

[IM Output]

Roberts

   Roberts:{_angle_}

[IM Text]

Roberts」カーネルは、前の「[Sobel](#sobel)」カーネルよりはるかに単純で、さらにタイトなエッジ位置(2ピクセルまで)を生成します。もちろん、それはノイズの影響を受けやすくもします。通常、このカーネルははるかに小さな 2x1 や 2x2 のカーネルで表されますが、3x3カーネルとして実装することで、カーネルを45度刻みで「巡回的に」回転できます。 例えば、これは45度の結果で、より一般的には「Roberts-Cross」カーネルとして知られています。 |

  magick face.png -define convolve:scale='50%!' -bias 50% \
         -morphology Convolve Roberts:45 face_roberts.png

[IM Output]
[Sobel](#sobel)」と同様、マルチカーネル処理を使って全方向から最大の傾きを生成することもできます。ただし今回は、4方向だけでなく8 x 45度方向が得られます。 |

   magick face.png -define morphology:compose=Lighten \
          -morphology Convolve 'Roberts:@' face_roberts_maximum.png

[IM Output]
このカーネルを180度回転しても(オフセットのため)反転した結果が生成されないことに注意してください。そのため、「[Sobel](#sobel)」でできるように畳み込みの数を半分にまとめることはできません。基本的に、1回の「[Roberts](#roberts)」畳み込みで生成される傾きは、実際の画像との整列から半ピクセルずれています。つまり、計算される傾きは「+1」と「-1」の値の間、ピクセルの間に位置しますが、中心の「-1」ピクセルに保存されます。しかしこれはまた、ピクセルの周りのすべての傾きを保存して加算することで、鋭いエッジ境界を強調するのにわずか2ピクセル(4ピクセルではなく)を使う、はるかに小さく鋭いエッジ検出が得られることも意味します。

Prewitt

   Prewitt:{_angle_}

[IM Text]

Prewitt」カーネルは「[Sobel](#sobel)」に非常によく似ていますが、特定のエッジ検出の正確な方向についてはるかに緩いです。そのため、結果は少しぼやけます。 |

  magick face.png -define convolve:scale='50%!' -bias 50% \
         -morphology Convolve Prewitt face_prewitt.png

[IM Output]

Compass

   Compass:{_angle_}

[IM Text]

これは「Prewitt Compass」カーネルで、「[Sobel](#sobel)」より強い方向感覚を持つとされています。 |

  magick face.png -define convolve:scale='50%!' -bias 50% \
         -morphology Convolve Compass face_compass.png

[IM Output]

Kirsch

   Kirsch:{_angle_}

[IM Text]

これはもう1つの強い方向感知エッジ検出器です。 |

  magick face.png -define convolve:scale='50%!' -bias 50% \
         -morphology Convolve Kirsch face_kirsch.png

[IM Output]

Frei-Chen

この組み込みでは3組のカーネルが提供されます。最初は「[Sobel](#sobel)」の「等方性」(均一方向)変種で、「2」の値が2の平方根に置き換えられたものです。

   Frei-Chen:[{_type_},][{_angle_}]

[IM Text]

上記のカーネルは、「Frei-Chen」カーネルの核心であるデフォルトの非重み付けカーネルです。 |

  magick face.png -define convolve:scale='50%!' -bias 50% \
         -morphology Convolve Frei-Chen face_freichen.png

[IM Output]
[Sobel](#sobel)」と同様、このカーネルは90度の倍数の角度を使って適用すべきです。物事を簡単にするため、(同じ重み付けの)2つのカーネルが提供されており、1つは上記のように直交用、もう1つは対角用です。

Frei-Chen:1

[IM Text]
Frei-Chen:2
[IM Text]

3番目のタイプの組は、特定の方向のエッジ検出だけでなく、鋭いエッジの実際の角度を判定するためにも使われる、9つの特別に設計され重み付けされたカーネルからなります。この場合の「type 」は「11」から「19」までの数値で、この組から9つのカーネルのいずれか1つを抽出できます。ただし「10」の「type 」値を与えると、9つすべての事前重み付けされたカーネルのマルチカーネルリストが得られます。

各カーネルが元画像に適用されその後結果が加算されてエッジ検出結果が
生成されます

これは [HDRI](basics.html#hdri) 版の ImageMagick を使って行うのが
最適です




   magick image.png \
          \( -clone 0 -morphology Convolve FreiChen:11 \) \
          \( -clone 0 -morphology Convolve FreiChen:12 \) \
          \( -clone 0 -morphology Convolve FreiChen:13 \) \
          \( -clone 0 -morphology Convolve FreiChen:14 \) \
          \( -clone 0 -morphology Convolve FreiChen:15 \) \
          \( -clone 0 -morphology Convolve FreiChen:16 \) \
          \( -clone 0 -morphology Convolve FreiChen:17 \) \
          \( -clone 0 -morphology Convolve FreiChen:18 \) \
          \( -clone 0 -morphology Convolve FreiChen:19 \) \
          -delete 0 -background Black -compose Plus -flatten \
          result.pfm




type  10 を与えると上に示した9つの重み付けカーネルすべてのマルチカーネルリストが
生成されますこれによりマルチカーネル合成を使って上記をはるかに簡単に
行えます...




    magick image.png -define morphology:compose=Plus \
           -morphology Convolve FreiChen:10 \
           result.pfm




ただし結果が意味するとされるものが何なのかは突き止められていませんこれが
実際にどう使われるかについて経験や知識をお持ちの方は他の人が使えるようここに
含められるよう私にお知らせください

Correlate ( )

[Convolve](#convolve)」メソッドが基本的に画像処理に使われるのに対し、「Correlate」メソッドはパターンマッチングのために設計されています。つまり、画像とそのカーネルの「相互相関」を実行し、画像内で与えられた形状の一致を探します。実際には、「[Convolve](#convolve)」と「Correlate」は同じ操作です。両者の唯一の違いは実際には非常に小さく、すなわちカーネルの x と y の反転(180度回転に相当)です。相関と畳み込みがどう動作し、互いにどう異なるかについて見つけた最良のガイドは、Class Notes for CMSC 426, Fall 2005, by David Jacobs です。

Convolution と Correlation の比較(非対称カーネルの効果)

上で述べたように、2つのオペレータ「[Convolve](#convolve)」と「[Correlate](#correlate)」は本質的に同じです。実際、ユーザーはしばしば、本当は相関を意味しているのに畳み込みと言います。また、相関の方が実際には理解しやすいメソッドです。中心の「原点」を中心に対称なカーネル(これは非常に典型的)の場合、2つのメソッドは実際に同じです。違いは、非対称または不均等なカーネルを使う場合にのみ明らかになります。例えば、ここでは「L」字型の「フラット」カーネルを「単一ピクセル」画像に対して使います。

  magick pixel.gif  \
         -morphology Convolve '3: 1,0,0
                                  1,0,0
                                  1,1,0' convolve_shape.gif

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

ご覧の通り、「[Convolve](#convolve)」は中心の単一ピクセルを拡大して、その周りに「L」字型を形成しました。原点自体が「近傍」の一部でなかったときでさえ。では、この例を繰り返しますが、代わりに「[Correlate](#correlate)」を使います。

  magick pixel.gif  \
         -morphology Correlate '3: 1,0,0
                                   1,0,0
                                   1,1,0' correlate_shape.gif

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

ご覧の通り、「[Correlate](#correlate)」も単一ピクセルを拡大して「L」字型を形成しましたが、それは「回転した」「L」字型でした。これが本質的に、これら2つのメソッドの唯一の違いです。「[Correlate](#correlate)」メソッドはカーネルを「そのまま」適用し、その結果、単一ピクセルが「回転した」形に拡大されます。一方、「[Convolve](#convolve)」は実際にカーネルの180度「回転した」形を使うので、各ピクセルが同じ非回転の形に拡大されます。「[Convolve](#convolve)」が実際にどう動作するかの素晴らしい例を見たい場合は、EECE \ CS 253 Image Processing, Lecture 7, Spatial Convolution も見ることをお勧めします。22ページの図では、私が上で行ったように、実際に「反転した」カーネルを単一ピクセルに適用しています。
この回転の違いは大したことではないように見えるかもしれませんが、数学の観点では、畳み込み操作(アスタリスク(「*」)記号で表される)は可換であり、カーネルと画像の両方が単なる値の配列(つまり2つの画像)として扱われる場合、F * G == G * F となることを意味します。また、畳み込みが結合的であり、( F * G ) * H == F * ( G * H ) となることも意味します。これについての詳しい情報はConvolution Properties, Wikipedia を参照してください。「[Correlate](#correlate)」操作は、(カーネルの回転によって)密接に関連しているにもかかわらず、可換でも結合的でもありません。基本的に「[Convolve](#convolve)」は数学的な「乗算」のように振る舞いますが、「[Correlate](#correlate)」はそうではありません。このすべての面倒の例外は、使われるカーネルが180度回転したときに同一である場合です。つまり、カーネルが「原点」を中心に対称な場合です。その特別な場合、両方の操作は同等の結果を生成します。人々を混乱させるのは、ガウシアンぼかし、ラプラシアンなど、畳み込みに使われるカーネルのほとんどが対称であり、その場合、実際に畳み込みをしているのか相関をしているのかが本当はどうでもよいということです。それで人々は気が緩んで意味があいまいになります。対称でない場合、つまり形状探索(次を参照)の場合や、Sobelのような方向性カーネルの場合にのみ、違いが本当に重要になるのです。

相関と形状探索

Correlate」メソッドの本当の用途(カーネル近傍を回転せずに「そのまま」適用する)は、提供されたカーネル内に見つかる形状とおおよそ一致する形状の物体を特定する、古いがシンプルなメソッドです。例えば、「L」字型のカーネルで「Correlate」を使い、上記の畳み込みメソッドの例で作成した画像を探索しようとすると、次のようになります...

  magick convolve_shape.gif -define convolve:scale='1!' \
         -morphology Correlate '3: 1,0,0
                                   1,0,0
                                   1,1,0' correlate.gif

[IM Output] [IM Output] [IM Output] _余談: 上記のカーネル画像の「黒い」領域はゼロの値を表します。このカーネルには負の値はなく、一致させる形状のための正の値だけです。

_

最終結果が明るくなりすぎて「ピーク」が白い点の海に飲み込まれるのを防ぐため、IM のカーネル正規化を使ったことに注意してください。ご覧の通り、「[Correlate](#correlate)」メソッドは、カーネルの「原点」が画像内の同じ形状とちょうど一致する点で最大の明るさを生成しました。しかし、形状の部分的な一致しか得られない場所では、それほど明るくない結果も生成します。一致した形状が多いほど、ピクセルは明るくなります。ただし、この場合「[Correlate](#correlate)」は成功しましたが、これは本当に良いやり方ではないと警告しておきます。例えば、非常に明るい領域では非常に多くの誤検出を生成することがあります。この問題は、画像の暗い背景に一致すべき領域に負の値を使うことで緩和できます。つまり、背景に一致しない領域は結果のピクセルをより暗くすべきです。

  magick convolve_shape.gif -define convolve:scale='1^'  \
         -morphology Correlate '4x5+2+2:  0 -1  0  0
                                         -1 +1 -1  0
                                         -1 +1 -1  0
                                         -1 +1 +1 -1
                                          0 -1 -1  0 ' correlate_pattern.gif

[IM Output] [IM Output] [IM Output] _余談: カーネル画像を明瞭にするため、正(前景)の値が白、負(背景)の値が黒、ゼロ(無関係)の値が透明になるようカーネル画像を生成しました。ただし、実際に使われるカーネルは数値の観点で完全に定義されており、その「近傍」は完全な矩形です。

_

ご覧の通り、前景ピクセルだけでなく背景ピクセルも一致させているので、一致のピークがはるかに顕著になりました。上記の特別な正規化フラグ「^」の使用に注意してください。これは、カーネル内の正と負の値を別々に正規化するので重要です。つまり、前景ピクセルと背景ピクセルを均等に探索したいのです。これは、HDRI 版の IM を使うか、または出力バイアス(上記参照)を適切に使うことで、与えられた形状の正と負の両方の一致を探索できることを意味します。例えば、ここでは正と負の両方の「L」字型を含むテスト画像に「L」字型探索を適用します。(表示される画像は拡大されています)

  magick test_morphology.gif  -bias 50% -define convolve:scale='50%^' \
         -morphology Correlate '4x5+2+2:  0 -1  0  0
                                         -1  1 -1  0
                                         -1  1 -1  0
                                         -1  1  1 -1
                                          0 -1 -1  0 ' correlate_bias.gif

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

出力バイアスは探索の通常の出力を中間色のグレーにし、一致する形状には、実際に「形状カーネル」に一致するピクセルの数に応じて、より明るいまたはより暗い色が与えられます。出力画像の実際の値を調べると、純白のピクセルと純黒のピクセルがそれぞれ1つ生成され、完全な一致を示しています。ただし、かなりの数のほぼ一致も存在します。負または「黒い」一致に興味がなければ、出力バイアスと「50%」スケーリング係数を取り除いて、非一致ピクセルが黒、完全な一致が白になるようにできます。「[Correlate](#correlate)」の一致画像を得たら、一致する「ピーク」を見つけようとする必要があります。これは別の相関を使って行えますが、必ずしもうまくいくとは限りません。より良いメソッドは、より正確なパターンマッチングメソッド「[HitAndMiss](morphology.html#hitmiss)」モルフォロジーを、この目的のために作られた特別な「[Peaks](morphology.html#peaks)」とともに使うことです。これは、より暗い色のピクセルだけに囲まれた単一ピクセルを見つけます。他の「[Peaks](morphology.html#peaks)」カーネルを使えば、「より緩い」一致を見つけられます。

  magick correlate_bias.gif  -morphology hitandmiss peaks:1.9 \
         -auto-level correlate_peaks.gif

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

そしてここで、形状の最良の一致が見つかった位置を簡単に見つけられます。ただし、一致の度合いは失われています。比較とサブ画像探索の「ピーク発見」セクションを見るとよいでしょう。ただし、Fred Weinhaus のスクリプト「[maxima](http://www.fmwconcepts.com/imagemagick/maxima/)」も見てください。FUTURE: 高速フーリエ変換を使った正規化相互相関で、非常に大きな画像(ソース画像とサブ画像の両方)で非常に高速な画像相関を生成する。

Correlation と HitAndMiss モルフォロジーの比較

私が表したカーネル画像を、Hit-And-Miss モルフォロジーメソッドが使うカーネルと比較すると、実際には同じものを表していることがわかります。 '[HitAndMiss](morphology.html#hitmiss)' '[Correlate](#correlate)'
前景 1.0」の値 1.0」の値(正規化前)
無関係 Nan」または「0.5」の値 Nan」または「0.0」の値
背景 0.0」の値 -1.0」の値(正規化前)
結果 前景の最小値を背景の最大値から減算します。そのため、完全な一致だけが正の結果を生成し、しきい値処理で二値の一致画像を生成します。 画像が形状にどれだけ近く一致するかの範囲を生成します。全体のパターンが存在する限り、一部の背景ピクセルが前景ピクセルより値が大きくなることもあり得ます。特定の「一致」ピークを見つけるのは難しい場合があります。負の一致を見つけることもできます。
ご覧の通り、それらは互いに対応しています。したがって、一方のカーネルをもう一方のカーネルに変換できます。ただし、「[Hit-And-Miss](morphology.html#hitmiss)」は、前景と背景に明確な差がある完全に正確な一致だけを見つけます。そのため、「[Correlate](#correlate)」よりもノイズやほぼ一致に対してはるかに寛容ではありません。一方、「[Correlate](#correlate)」は線形画像処理を使って、より具体的には高速フーリエ変換を使って実行できます。これにより、より大きなパターンやカーネルでのパターンマッチングをはるかに高速にでき、特に複数のパターンが関わる場合、画像とパターンを周波数領域に変換するコストを節約できます。これは実画像でも機能しますが、いくらかの前処理とHDRIの使用も必要かもしれません。どちらを使うかは、本当にあなた次第であり、どんな結果を求めているか次第です。完全な一致だけか、より多くのエラーを伴うほぼ一致か、そして高速なアルゴリズムを使う可能性かです。より大きな画像内で小さなカラー画像の完全な一致を見つけるには、「magick compare」プログラムのサブ画像探索機能が、「[Hit-And-Miss](morphology.html#hmt)」や「[Correlate](#correlate)」メソッドのいずれよりもはるかに良いメソッドを提供することに注意してください。これは、サブ画像マッチングに「色ベクトル差の最小二乗」を使うからで、それは一致結果のより良い指標を生成できます。ただし、特に大きな画像では同じくらい遅いです。

近傍カウント

畳み込みを使えるより珍しいことの1つは、近傍カウントとして知られています。つまり、画像内の各ピクセル点を取り囲む特定の領域内にどれだけのピクセルが存在するかを把握することです。

近傍のカウント

基本的に、非常に単純な畳み込みカーネルを使えば、二値画像内の特定の点を取り囲む近傍の数のカウントを含む画像を作成できます。サイズ「1.5」のリングカーネルで畳み込むことで、近傍カウントが得られます。これは小さな領域内の各ピクセルの近傍をカウントし、前後の個々のピクセルの拡大を示したものです(画像拡大スクリプトで生成)...

  magick area.gif -define convolve:scale=\! \
         -morphology Convolve Ring:1.5 neighbour.gif

[IM Output] [IM Output]

ご覧の通り、すべてのピクセルのグレーレベルは、エッジに沿った任意の仮想ピクセル近傍を含めて、いくつの近傍を持つかを示しています。現在のピクセルをカウントに含めたい場合は、代わりに正方カーネルを使えます。適切な変換(レベル調整を含む)を行い、PbmPlus ファイルフォーマットを使えば、上記のグレーレベルを、もしそれが欲しいなら実際の数値に変換できます。

  magick neighbour.gif +depth +level 0,8 pgm: | pnmnoraw | tail -n +4

[IM Text]

実際の形状の内側にあるピクセルを除外したい場合は、強い負の中心ピクセルを持つカーネルを使い、その後(HDRI 版の IM を使っているなら)負の結果をクランプできます。大きな負の中心を囲む正の1のカーネルをちょうど生成する1つの簡単なメソッドは、標準の離散ラプラシアンカーネルを負にスケーリングすることです。

  magick area.gif -define convolve:scale=-1\! \
         -morphology Convolve Laplacian:0 -clamp neigh_edge.gif

[IM Output] [IM Output]

もちろん、興味のないピクセルを除去するために元画像をマスクとして使うこともできました。

ライフゲーム

1970年、英国の数学者ジョン・ホートン・コンウェイは、Scientific American 誌に、非常に人気となった特別なシミュレーションを発表しました。それは今やコンウェイのライフゲームとして知られています。それは、各点が「生」または「死」のいずれかである点のグリッドに基づいていました。次に、どの「セル」が次の「世代」で「生」または「死」と分類されるかは、それらを取り囲む生きた近傍セルの数のみに純粋に基づく、非常に単純な一連のルールに依存していました。

  • 近傍は、各「セル」を取り囲む8つのピクセルです。
  • 「生」のセルは、2つまたは3つの近傍を持つ場合に生き続けます。
  • 「死」のセルは、ちょうど3つの近傍を持つ場合に「生」になります(誕生)。
  • それ以外の場合、セルは「死」になるか、「死」のままになります。

二値パターンに対するこれらのルールの結果は驚くべきもので、拡大したり縮小したり、振動したり、グリッドを横切ってゆっくり移動したりするように見える「セル」のクラスタが得られます。それは、より大きな「ライフパターン」の「DNA」型複製を生成できるかどうかを見る、理論研究の主要な焦点となりました。余談: それは可能だったようですが、非実用的なほど脆弱で、それが現在の DNA 生命をはるかに驚くべきものにしています。それはまた、非常に小さなスケールで非常に単純なルールを使って大きな効果を生成・研究する方法として、他の形のセルオートマトンの研究と実装への大きな関心も呼び起こしました。化学で原子や分子のレベルで起こることに似ていますが、より大きな複雑さを伴います。それでは、ImageMagick を使って「ライフ」を実装しましょう。まず物事を簡単にするため、「生」のセルを白、「死」のセルを黒にします。そうすれば、8ピクセルの近傍で各セルを取り囲む「白い」ピクセルだけをカウントすればよいのです。ただし、黒と白を入れ替えても実装できますが、どう行われるかを追うのが難しくなります。しかし、ルールは中心のセルが生きているか死んでいるかに強く依存します。そのため、「死」のセルの近傍カウントを「生」のセルのものから分離する必要があります。それは、中心のセルにすべての近傍の合計より大きな値を与えることで簡単に行えます。「10」の値がこれに適しています。それは、最大近傍カウントの8より大きな、きれいな丸い数字です。それにより、「ライフゲーム」畳み込みカーネルは次と同等になります..

    '3: 1,  1,  1
        1, 10,  1
        1,  1,  1'

この結果は、各ピクセルの周りの8つの近傍のカウント(「白」の場合)に、中心のピクセルが「生」または「白」の場合は10の値を加えたものになります。そのため、このカーネルの値は、死んだピクセルでは「0」から「8」、生きたピクセルでは「10」から「18」のいずれかになります。このカーネルを20の値でスケーリングすると(実際にはグラデーションを生成するため「0.05」でスケーリング、下記参照)、21の可能なグレーレベルを持つ画像が生成されます。つまり、「0」グレーレベルの値には「黒」が、「21」グレーレベルには白い値が得られますが、カーネルが実際にそのような値を生成できるわけではありません。さて、上記のカーネルで生成された結果の近傍カウント「グレーレベル」を、「ライフルール」に従った適切な「生死」の結果に変換するため、「ライフゲーム 」のルールをカラールックアップテーブル画像にエンコードできます。

  magick -size 21x1 xc:black -fill white \
          -draw 'point 3,0  point 12,0  point 13,0' \
          life_clut.gif
  enlarge_image -25.3 -ml 'Life Rules' life_clut.gif life_clut_enlarged.png

[IM Output]

この画像は非常に小さいので、上に表示するために画像拡大スクリプトを使って、各ピクセルが明確に分離された、より大きなバージョンを生成しました。基本的に、最初の10ピクセルは「死んだセル」のための処理、次の10ピクセルは「生きたセル」のための処理です。左側の最初の白いピクセル(死んだセルの周りの近傍カウント = 3)は「誕生」で、右側の2つの白いピクセル(生きたセルの隣の近傍カウント2と3)は、既存の「生きたセル」が生き続けることを許します。他のいかなる結果も、結果を黒(死)のままにします。カラールックアップテーブルが21ピクセル長なのは、20のスケーリング係数で割るからで、それは0から20、つまり21の異なるグレースケールレベルの値を生成できることを意味します。中心(セルの前の状態)に10とは異なる値を、スケーリングに20とは異なる値を実際に使うこともできますが、これらは扱いやすい数字です。要約すると、畳み込みカーネルを20で割り、畳み込み結果(グレーレベル)を正しい出力色値に合わせるため、(整数補間を使う)21ピクセル長の CLUT を使います。余談: この「ライフルール」CLUT は、一般的なセルオートマトンのルールテーブルと見なせます。近傍カウントに使われる近傍パターンも、セルオートマトンの一部です。この技術は、Cellular Automata Rules LexiconRules Tables セクションでも、それがリストする一般的な「限界のない」形のセルオートマトンを定義する方法として概説されています。基本的に、ほとんどどんなオートマトンも、そのような近傍/テーブルの組み合わせを使って定義できますが、ほとんどはより単純化された形を使って定義されます。それでは、これを「ライフ」パターンを含む画像に複数回適用して、パターンがある世代から次へどう変化するかを見て、期待通りに機能していることを確認しましょう。

  magick -size 15x15 xc:black -fill white \
         -draw 'line  3,2 3,4  line 10,10 12,10  point 10,11  point 11,12' \
         life_gen_000.gif
  magick life_gen_000.gif -define convolve:scale=0.05 \
         -morphology Convolve '3:1,1,1 1,10,1 1,1,1' \
         life_clut.gif -interpolate integer -clut \
         life_gen_001.gif
  magick life_gen_001.gif -define convolve:scale=0.05 \
         -morphology Convolve '3:1,1,1 1,10,1 1,1,1' \
         life_clut.gif -interpolate integer -clut \
         life_gen_002.gif
  magick life_gen_002.gif -define convolve:scale=0.05 \
         -morphology Convolve '3:1,1,1 1,10,1 1,1,1' \
         life_clut.gif -interpolate integer -clut \
         life_gen_003.gif
  magick life_gen_003.gif -define convolve:scale=0.05 \
         -morphology Convolve '3:1,1,1 1,10,1 1,1,1' \
         life_clut.gif -interpolate integer -clut \
         life_gen_004.gif

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

上記の画像は拡大されていることを覚えておいてください。生成された元の「極小」画像を見るには、拡大画像をクリックしてください。ご覧の通り、「ライフ」パターンは(あなたがパターンに精通しているなら)あるべき通りに振る舞います。左上隅の「ブリンカー」は前後に反転し、下部の「グライダー」は、ライフルールを反復した4「世代」にわたって、それに向かって1対角ステップ移動しました。[IM Output] そしてこれはゴスパーのグライダー銃として知られるより大きな例で、特別なライフパターンから60フレームのアニメーションを生成します。使われている画像の実際のサイズは右に表示されていますが、より見やすくするためアニメーションをスケーリングします。

  magick glider_gun.gif life_pattern.gif
  for i in `seq 59`; do
    magick life_pattern.gif -define convolve:scale=0.05 \
           -morphology Convolve '3:1,1,1 1,10,1 1,1,1' \
           life_clut.gif -interpolate integer -clut \
           -write life_pattern.gif miff:-
  done | magick - -scale 500% \
                -set delay 10 -layers Optimize -loop 0  glider_gun_anim.gif
  magick glider_gun.gif -scale 500% life_pattern.gif

[IM Output] [IM Output]

グライダーが下端で「爆発する」理由は、convolve が使うデフォルトの「仮想ピクセル」処理と、画像の境界を超えた際のライフ情報の損失によることに注意してください。より多くのライフパターン画像はLife Pattern Catalog で見つけられますが、上記のライフ処理器で使うには画像を再着色(反転)する必要があります。上記を、特定の入力画像のライフシーケンスを生成できるスクリプトにまとめるのは、誰かの練習問題として残しておきます。
これは、IM が処理できる「セルオートマトン 」の全範囲のほんの一例です。もちろん、「ライフ」と「セルオートマトン」のためのより高速な専用プログラムが多数あり、一般に全く同じことをしますが、IM もそれを行えるほど柔軟であることを示したかったのです。結果は単純な二値画像なので、IM のモルフォロジーメソッド、例えばHit and Miss パターン探索相互相関を使って特定のライフパターンを探索することもでき、IM をライフ研究に使うことを、遅いとはいえより実用的にします。