ImageMagick の例 —
形状の形態学

索引
ImageMagick の例 序文と索引
形態学入門
基本的な形態学的方法
差分形態学的方法
低レベル形態学的方法の使用
ヒットアンドミス(HMT)パターンマッチング
距離形態学的方法
条件付きまたは制約付き形態学
形状からスケルトンを生成する。 開発中
形態学は、周囲の他のピクセルの「近傍」に基づいて、さまざまな方法で画像を変更します。これは、エッジからの距離、スケルトンまたは中心線軸までの細くするなど、形状の拡大と縮小(膨張/浸食)にいたるまで、幅広い効果をもたらす可能性があります。ぼかしやシャープニングなどの手法を提供する、より古い「畳み込み」手法でさえ、ある意味では形態学的方法の一種です。本質的に、形態学は、画像内にあるオブジェクトの形状の修正、決定、発見を目的としています。

形態学入門

形態学はもともと、画像内の形状の構造をクリーンアップして研究するための方法として開発されました。これは、画像内の各ピクセルをさまざまな方法で隣接ピクセルと比較することにより、そのピクセルを追加または削除し、明るくしたり暗くしたりします。おそらく繰り返し、画像全体に適用することで、特定の形状を見つけて、削除したり、変更したりできます。たとえば、ピクセルが白で、他の白ピクセルに完全に囲まれている場合、そのピクセルは明らかに画像のエッジにはありません。その後、エッジピクセルのみをオンにしたままにするために、そのピクセルを黒にすることができます。「EdgeIn」として知られる方法(下記参照)。このプロセス全体は実際には、「構造要素」または「カーネル」の定義に依存しており、これは、特定の形態学的方法についてどのピクセルを「隣接」と分類するかを定義します。この「近傍」のサイズと形状は、まさにあなたが達成しようとしていること、または画像内で具体的に探しているものによって決まることがよくあります。以下は、さまざまなカーネルの例です。これらは、(特別なスクリプト「kernel2image"」を使用して)画像に変換され、中心ピクセル「原点」の周りのいくつかの「近傍」を示しています。
[IM Output] [IM Output] [IM Output] [IM Output] [IM Output] [IM Output] [IM Output] [IM Output]
画像は、カーネルの個々の要素を強調するために拡大されており、ご覧のとおり、一般的なカーネルは非常に小さいことがよくあります。実際、上記に示されている「ディスク」カーネルは実際には「[Raw Disk Kernel Image]」であり、上記で示されている最大のカーネルの1つです。「カーネル」は実際には画像ではありません。単に、1つの要素がカーネルの「原点」として指定されている浮動小数点値の配列です。この特別な要素は、定義された近傍によって「影響を受ける」ピクセルの場所であり、通常は対称カーネルの中央ピクセルですが、必ずしもそうとは限りません。これらは、可能な近傍のほんの一例であることに注意してください。一部のカーネルは、そのカーネルに固有の「半径」引数を増やすことによって通常はサイズを大きくできますが、特殊な目的で使用されるカーネルは固定サイズです。最初の2つのような単純なカーネルの場合、形態学的方法を繰り返す(反復する)ことで、カーネルの有効な「サイズ」を大きくし、「原点」(マークされているとおり)からさらに離れたピクセルに影響を与えることができます。ただし、これは常に機能するわけではなく、予期しない結果を生む可能性がありますが、より大きなカーネルを直接使用する場合よりも高速になることがありますが、これも常に当てはまるわけではありません。形態学の研究論文でカーネルと呼ばれている「構造要素」または「SE」の最終的なサイズと形状は、この形状よりも大きくまたは小さい画像要素を見つけて強調または削除する手段として重要です。これにより、形態学は画像内のさまざまな要素を分類する手段として非常に強力になります。ただし、カーネルが大きいほど、形態学的方法にかかる時間が長くなるため、カーネルを小さく保つ方が良いでしょう。最後のカーネルを除く、すべてのカーネルは実際に成形されています。透明な部分は、カーネルの定義された「近傍」の一部ではありません。つまり、有効な値がなく、形態学計算には参加しません。「コーナー#0」の前の最後のカーネルは、「オン」値だけでなく、「オフ」値も「形状」の一部として持っています。「オン」値と「オフ」値の両方、および透明な値(形状の一部ではない)は、ヒットアンドミスおよび関連するメソッド(下記参照)にとって重要です。この特定のカーネルは、画像内のバイナリ形状の「コーナー」ピクセルを見つけるためのカーネルのシリーズの最初のものです。上記で示されている最後の「カーネル」は、大きな長方形(正方形)の領域全体で完全に定義されています。また、他のカーネルは1(白)、0(黒)、または特別な「未定義」値のみを使用しますが、このカーネルの値は実際にはエッジでほぼゼロ(ほぼ黒)から中心で最大(純粋な白)の値まで範囲があります。ただし、そのようなカーネルは、他のカーネルの通常の範囲をはるかに超える、負の値または非常に大きな値を使用することもできます。カーネルは単なる値の配列であり、これらの値は0から1の範囲だけでなく、任意の値を持つことができることを忘れないでください。このタイプのカーネルは、「畳み込み演算」で特に重要であり、これは形態学自体よりもはるかに長い間存在する特別な方法です。その結果、IMには、このタイプの組み込みまたは「名前付き」カーネルが非常に多くあります。これは、IMの例の次のセクション「画像の畳み込み」で詳しく説明します。すでに述べたように、カーネルは実際には画像ではありません。単なる浮動小数点値の配列です。後で、これらの実際の値(上記で表示のために画像に変換されたもの)を見ていきます。

形態演算子

-morphology」演算子は、ユーザーに多くのアクション制御を提供するため、非常に複雑です。

  -morphology {method}[:{iterations}]   {kernel}[:[k_args}]
少なくとも2つのアイテム、形態学の「メソッド」(演算子に画像に適用する操作の種類を指示する)と「カーネル」(最終結果に影響を与える「隣接」ピクセルを指定する)を提供する必要があることに注意してください。どちらも同様に重要であり、どちらも大きな影響を与える可能性があります。使用可能なメソッドのリストは、「-list morphology」を使用して取得できます。IMに含まれている組み込みカーネルのリストは、「-list kernel」で確認できます。後で、さまざまなメソッドと、それらのメソッドが使用できるカーネルについて説明します。
-morphology」演算子(基本メソッド)と初期のカーネルセットは、私が中国で休暇中に、2009年12月から2010年1月にかけてImageMagickバージョン6.5.9-0に追加されました。

ただし、古くから関連する「-convolve」メソッドを使用して、簡略化された「正方形」カーネル形態学を実行できます。下記の代替の基本的な形態学的手法を参照してください。

基本的な組み込み形状カーネル

カーネルはすべての形態変換メソッドに共通であり、様々なメソッドの結果は選択されたカーネルに大きく依存するため、最初にカーネルの定義または選択方法を見ていきます。優れたカーネルの選択肢は既に事前に定義されており、多くの場合、それら以外を探す必要はありません。「-list kernel」を使用することで、事前に定義された組み込みカーネルのリストを取得できます。すべてのカーネルは特定のサイズを持ち、通常は辺に奇数のピクセルを持つ正方形で、その中心がカーネルの「原点」になります。しかし、ご覧のように、「-morphology」演算子は、この制限に限定されません。組み込みカーネルで使用される最も一般的なk_argument、そして一般的に最初に与えられる引数は「radius(半径)」です。これは、カーネルの典型的な奇数サイズの正方形近傍の大きさを定義します。最終的なカーネルサイズは、一般的に半径の2倍プラス1(中心ピクセル用)になります。つまり、「radius」が「2」の場合、5×5ピクセルの正方形のカーネルが作成されます。「radius」は通常、最終的なカーネルのサイズ、したがって画像に対する形態変換の全体的な速度を定義しますが、特に畳み込みカーネルでは、値がカーネルサイズよりも結果に大きな影響を与えるため、最も重要な要素ではない場合があります。「radius」を0に設定するか、未定義のままにした場合、「radius」は、関連するカーネルに応じて、適切な値または最も一般的に使用される値に自動的にデフォルト設定されます。 [IM Output]

Unity(ユニティ)

これは、「No-Op(何もしない)」カーネルが必要な場合に特に使用される特殊なカーネルです。このカーネルを使用するほとんどの形態変換メソッドは、元の画像を再現するか、空白の結果を生成します。カーネルには引数はありません。このまったく同じ単一要素カーネルは、「Disk:0.5」を使用して生成することもできます。これにより、カーネルの生成の一部としてスケーリング引数を指定することもできます。[IM Output]

Diamond(ダイアモンド)

最も最小限の、しかしおそらく最も単純ではないカーネルは、「Diamond」組み込みカーネルです。基本的なカーネルを見る簡単な方法は、黒い背景に白いピクセルが1つだけある画像に対してDilate(膨張)形態変換メソッドを使用することです。これは基本的に、単一ピクセルをカーネル近傍の「形状」に展開します。以下は、「Dilate」を最小限の「Diamond」組み込みカーネルで使用し、結果を大きくスケーリングしてより見やすくした結果です。

  magick xc: -bordercolor black -border 5x5 pixel.gif
  magick pixel.gif -scale 800% pixel_mag.gif
  magick pixel.gif -morphology Dilate Diamond \
                    -scale 800% k_diamond.gif
[IM Output] ==> [IM Output]
IMの例にあるすべてのカーネル画像の結果は、個々のピクセルが見えるように拡大されていることを覚えておいてください。実際には、表示しているすべてのカーネルと結果は、あるべきように非常に小さいです。この場合、膨張されている画像はサイズがわずか11×11ピクセルで、表示のために8倍に拡大されています。
これは実際には形態変換にとってかなり優れたカーネルであり、基本的に最も最小限の実用的な近傍を定義しています。元のピクセルと、直接接触している4つのピクセルです。このタイプのカーネルの別の名前は「Z4」構造要素です。「プラス」記号のような小さな形をしています。ダイアモンドの形状は、半径が増加するにつれて明らかになります。このカーネルのオプションのk_argは、次のように2つの値を取ることができます。

     Diamond[:{radius}[,{scale}]]
すべての形状カーネルにおいて、最も重要な引数はradiusであり、前述のように、中心「原点」から最も近いエッジまでの距離を表す整数です。そのため、最終的な「Diamond」カーネルは(radiusの2倍プラス1)を含む正方形で、ダイアモンドの形状が含まれています。以下は、より大きなradiusを使用して大きなカーネルを生成した結果です。

  for r in 1 2 3 4; do
    magick pixel.gif -morphology Dilate Diamond:$r -scale 800% k_diamond:$r.gif
  done
[IM Output]
Diamond:1
(デフォルト)
[IM Output]
Diamond:2
[IM Output]
Diamond:3
[IM Output]
Diamond:4
もう1つのk_argumentscaleであり、デフォルト値は1.0です。通常、これはカーネルによって使用される実際の値を形状を形成するために変更するために使用されます。これは一般的にConvolve(畳み込み)グレースケール形態変換などの特殊なメソッドにのみ重要です。[IM Output]

Square(スクエア)

Square」は、他の代替技術を使用して適用するのが最も簡単であるため、形態変換で最も一般的に使用されるカーネルです。ただし、最も最小限のカーネルではありません(上記の「Diamond」を参照)。
デフォルトでは、「Square」カーネルは「中心」の周囲の3×3ピクセルの近傍を使用します。

  magick pixel.gif  -morphology Dilate Square -scale 800% k_square.gif
[IM Output]
基本的に、これは元のピクセルのすべての8つの隣接ピクセルが、そのピクセルの近傍の一部として分類されることを意味します。その結果、ピクセルの平均化や、形状の1ピクセル単位の拡大/縮小に適したカーネルとなります。すべての形状カーネルと同様に、上記のDiamond Kernelに示されているものと同じk_argumentsを受け取ります。最初の引数radiusが最も重要です。

  for r in 1 2 3 4; do
    magick pixel.gif  -morphology Dilate Square:$r -scale 800% k_square:$r.gif
  done
[IM Output]
Square:1
(デフォルト)
[IM Output]
Square:2
[IM Output]
Square:3
[IM Output]
Square:4
前述のように、このカーネルのデフォルト(radius=1)は3×3の正方形であり、「Z8」構造要素(関与する直近の隣接ピクセルの数)として一般的に知られています。[IM Output]

Octagon(オクタゴン)

Octagon」カーネルは、8辺の形状をしたカーネルです。「Octagonal Distance Metric(八角形距離メトリック)」と一致するように特別に設計されました。これらは非常に異なるカーネルであるため、混同しないでください。以下は、小さな半径の結果として得られるカーネルです。
[IM Output] [IM Output] [IM Output] [IM Output] [IM Output]
半径1では、「Diamond」カーネルと同じカーネルが得られます。このため、デフォルトのオクタゴンのサイズは半径「2」です。
この時点からは、特別なkernel2imageスクリプトを使用してカーネルの画像を生成します。これは(上記のように)生の「dilate-scale」メソッドを使用するよりもはるかに明確です。ただし、カーネルは一般的に非常に小さいですが、OctagonカーネルとDiskカーネル(次を参照)は、特定の用途では非常に大きくなる可能性があることを覚えておいてください。

Octagon」カーネルは、「Octagonal」距離カーネルとともに、IM v6.6.9-4に追加されました。
[IM Output]

Disk(ディスク)

Disk」カーネルは、予想どおり円形です。非常に大きな形態変換カーネルが必要な場合によく使用されます。ただし、エイリアシングされたブール円のことに注意してください。ただし、ディスクのradius引数は浮動小数点数値にすることができ、小さな半径を使用してさまざまな形状を作成できます。
[IM Output] [IM Output] [IM Output] [IM Output] [IM Output] [IM Output]
[IM Output] [IM Output] [IM Output] [IM Output] [IM Output]
Disk:4.3」カーネルはデフォルトであり、私が最初の真のディスク形状と見なしているものです。このサイズ以上のディスクは、画像の形状を全体的に丸めたり、滑らかにしたりするのに特に適しています。ディスクを含むカーネルの最終的なサイズは、「radius」値を四捨五入した値に2を掛け、1を加えたものです。そのため、デフォルトの「Disk:4.3」カーネルのカーネルサイズの半径は4であり、最終的なカーネルサイズは4×2プラス1となり、ディスク形状を保持する9×9のカーネルが生成されます。1未満(ただし0ではない)の値は常に単一ピクセルのカーネルを生成することに注意してください。ただし、これはあまり役に立ちません。その後、カーネルは主に、前のカーネルタイプを使用して生成できるカーネルを生成する傾向があります。真のディスク形状のカーネルが現れ始めるのは、半径が大きくなったときだけです。最も重要なことは、分数半径のディスクの方が、整数半径を使用するよりもはるかに効果的であるということです。ディスクの側面に不自然な単一ピクセルが生成されないように、約0.3から0.5の分数を加えることをお勧めします。[IM Output]

Plus(プラス)

Plus」カーネルは、他の形態変換形状カーネルとは少し異なり、ピクセルの周囲の単純な「近傍」ではなく、特定の「形状」を表すように設計されています。このカーネルでより大きな「radius」を使用しても、カーネルのサイズが単純に増加するのではなく、結果のプラス記号の腕が長くなります。ただし、腕の太さは増加しません。
[IM Output] [IM Output] [IM Output] [IM Output]
Plus」カーネルのデフォルトサイズは半径2で、中心「原点」の周囲に2ピクセルの「腕」を生成します。「Plus:1」カーネルは、デフォルトの「Diamond」カーネルと同じです。「Plus」カーネルは、通常の形態変換メソッドには一般的に使用されず、そのような目的には避けるべきであることに注意してください。ただし、後でスケルトン情報を表示するために使用するように、画像内の単一の点を検出して強調表示したい場合は非常に便利です。基本的に、個々の「点」が画像内のどこに位置しているかを正確に知る必要なく、記号の描画の方法を提供します。 [IM Output]

Cross(クロス)

Cross」カーネルは「Plus」とまったく同じですが、45度回転しています。これは、様々な点の位置をマークするためにピクセルを拡張するのに適した特別なカーネル形状でもあります。
[IM Output] [IM Output] [IM Output] [IM Output]
[IM Output]

Ring(リング)

Ring」カーネルは、「Plus」カーネルと同様に、ピクセルのマーク付けや画像へのパターンの生成のための特別な「形状」カーネルとして設計されています。ただし、1つの半径だけを取るのではなく、2つの半径を取ることができ、Disk Kernelsと同じ方法で定義されます。

     Ring[:{radius1}[,{radius2}[,{scale}]]]
これは、与えられた2つの半径の順序に関係なく、2つの半径の間に落ちるピクセルを「オン」にします。半径が指定されていない場合、デフォルトで「2.5」と「3.5」の半径になり、「Ring:2.5,3.5」が生成されます。これは、ピクセルを囲むのに理想的な中空の八角形のリングのように見えます。2つの半径を変えることで、任意のサイズと厚さの「リング」を作成できます。半径を少し変更すると、エッジの周りの非常に小さな数のピクセルが追加および削除され、リングの外観を細かく制御できます。2つの半径が互いに1ピクセル以内にある場合、まばらに離れた点で構成されるリングを生成することもできます。これは、特殊な目的の近傍として役立ちます。小さな半径では、ボックス状のカーネルも生成され、これも役立ちます。2番目の半径が指定されていない場合、デフォルトで「0.5」の値になり、中心「原点」ピクセルを除く完全なディスクを効果的に定義します。言い換えれば、「原点」ピクセルを除くディスクカーネルです。以下は、生成できる多くの「Ring」カーネルの例です。
[IM Output] [IM Output] [IM Output] [IM Output] [IM Output] [IM Output] [IM Output] [IM Output] [IM Output] [IM Output] [IM Output] [IM Output] [IM Output] [IM Output] [IM Output] [IM Output] [IM Output] [IM Output] [IM Output] [IM Output] [IM Output]
ご覧のように、2つの半径を注意深く調整することで多くの可能性があり、画像内の関心のある場所を示す良い方法を提供します。[IM Output]

Rectangle(レクタングル)

Rectangle」カーネルは、上記の「Square」カーネルと密接に関連しており、デフォルトでは同じ3×3の正方形カーネルを生成します。しかし、単純な半径引数ではなく、「geometry」引数を指定して、必要な長方形カーネルの正確なサイズを指定できます。以下は、いくつかの仕様と、それらが生成するカーネルの画像です。
[IM Output] [IM Output] [IM Output] [IM Output]
[IM Output] [IM Output] [IM Output] [IM Output]
デフォルトでは、カーネルは近傍の「origin(原点)」をカーネルの正確な「center(中心)」に設定しようとします。しかし、偶数サイズの矩形の場合、中心のすぐ上および/または左の点を適切に選択します。ただし、中心からずれた原点を指定することもできます。この特定のカーネルは、長い水平線と垂直線の定義にも優れており、画像内でそのようなオブジェクトを検索できます。これについては後で詳しく説明します。現時点では、矩形に*scale*係数を指定することはできません。すべてのカーネル値は1.0にのみ設定されます。

ユーザー定義DIYカーネル

組み込みカーネルに限定されるわけではなく、独自のカーネルを指定し、カーネルで使用したい正確な値を指定することもできます…

   "[{geometry}:] {value}, {value}, {value},....."
「*geometry*」の指定は、基本的に前の「Rectangle」カーネルの引数とまったく同じです。カーネルのサイズ、およびオプションで近傍「origin(原点)」の「offset(オフセット)」を指定します。数値が1つだけ指定されている場合、正方形カーネルの次元が想定されます。
geometry値は「radius(半径)」引数ではなく、全体のカーネルサイズであることに注意してください。
「*geometry*」または「:」が指定されていない場合、「旧式」の指定を使用しています。与えられたすべての値を保持できるだけの大きさの奇数サイズの正方形カーネルが生成されます。これは推奨されておらず、旧バージョンのImageMagickとの後方互換性のためにのみ提供されています。「:」(これは「*geometry*」指定の後で必須です)の後には、コンマおよび/または空白で区切られた*width* × *height*の浮動小数点値を指定します。「NaN」(「Not a Number」の意味)または「-」を単独で使用して、カーネルのこの点が形態学的近傍の一部ではないことを指定できます。
たとえば、幅3の正方形カーネルの指定を示します。これは、単一ピクセルの画像の畳み込みぼかしに使用できます。

  magick pixel.gif   -morphology Convolve \
            "3:  0.3,0.6,0.3   0.6,1.0,0.6   0.3,0.6,0.3" \
                                         -scale 800%  k_user_3.gif
[IM Output]
単一ピクセルでは、ConvolveDilateとほぼ同じように機能しますが、Convolveはカーネルの値を使用して、近傍の値を拡張して加算します。Dilateは、一方、一般的にオン/オフ(ブール値)の形状とすべての近傍の最大値を使用して機能します。ただし、ブール値の形状を持つ単一の孤立したピクセルに適用した場合、同じ結果が得られます。個々の矩形カーネル定義の行を分離するために、入力文字列に追加のスペース(または改行)を追加できることに注意してください。
ここでは、5×3の矩形領域を定義しましたが、特別な「nan」(数値ではない)値を使用して角を切り取り、楕円形のカーネルを作成しました…

  magick pixel.gif   -morphology Dilate \
            "5x3: nan,1,1,1,nan   1,1,1,1,1   nan,1,1,1,nan " \
                                    -scale 800%   k_user_5x3.gif
[IM Output]
最後に、カーネルの「origin(原点)」の周囲に「L」字型を形成する矩形近傍を指定する例を示します。「nan」の代わりに「-」を使用して、カーネルの一部ではない部分を指定しました。このカーネルの原点は、独自の近傍の一部でさえなく、カーネルの矩形境界内のどこにでも配置できます。

  magick pixel.gif   -morphology Dilate \
            "2x3+1+1:   1,-   1,-   1,1   "  -scale 800% k_lman.gif
[IM Output]
ご覧のとおり、ユーザーカーネルの指定は非常に柔軟性があり、畳み込みカーネル(多くの分数を含む)や形態学的メソッド用の「近傍の一部ではない」要素を含む形状カーネルなど、ほぼあらゆるタイプのカーネルを指定できます。

画像をユーザーカーネルに変換する

DIYカーネルの生成を容易にするために、「image2kernel」スクリプトを使用してカーネルを作成できます。たとえば、ここでは小さな旗(  )をユーザーカーネルデータファイル(「flag_kernel.dat」)に魔法のように変換してから、それを用いていくつかのピクセルを含む画像を膨張処理します。

  magick -size 80x80 xc:black -fill white \
          -draw 'point 20,15 point 55,30 point 40,60'  points_pixels.gif
  image2kernel -qgm flag.gif flag_kernel.dat

  magick points_pixels.gif \
             -morphology Dilate @flag_kernel.dat \
           flagged_points.gif
[IM Output] - [IM Output] ==> [IM Output]
カーネルの画像を生成できるカーネルの画像の生成も参照してください。この手法については、シンボルの描画の代替手段でも説明されています。

形態演算の繰り返し(反復)

ご覧のとおり、より大きな近傍に形態処理を適用するために、より大きなカーネルを生成できます。ただし、ほとんどの場合、大きなカーネルを使用するよりも、形態演算子を複数回繰り返す(反復またはループする)方が高速な代替手段です。つまり、演算子の効果はさらに広がり、大きなカーネルを使用した場合と同じ基本的な効果が得られますが、大きなカーネルを使用した場合の追加の計算コストは発生しません。
たとえば、これは「Diamond:3」カーネルを使用した単一ピクセルの膨張処理の例です…

  magick pixel.gif  -morphology Dilate Diamond:3 -scale 800% k_diamond_x3.gif
[IM Output]
しかし、より小さな「Diamond」カーネル(半径1)を3回使用しても同じ結果を得ることができます…

  magick pixel.gif  -morphology Dilate Diamond \
                     -morphology Dilate Diamond \
                     -morphology Dilate Diamond  -scale 800% k_diamond_x3.gif
[IM Output]
依然として非常に小さい3×3のカーネルを使用していますが、基本的な形態演算を3回繰り返して、より大きなカーネルを使用した場合と同じ効果を生み出しています。実際、このように小さなカーネルを繰り返す方が、はるかに大きなカーネルを使用するよりもはるかに高速です。
大きな「Diamond:3」カーネルには、画像のピクセルごとに81個の要素を処理する必要があります。しかし、より小さな「Diamond」カーネルを3回繰り返すと、画像のピクセルごとに3×9、つまり27個のカーネル要素を処理する必要があります。この場合、3倍高速です。

このケースでは速度の向上はそれほど多くありませんが、カーネルのサイズが大きくなるにつれて節約効果ははるかに大きくなります。
形態演算の繰り返しは非常に一般的であるため、演算を複数回繰り返すのではなく、IMにその回数だけ演算をループまたは反復させることができます。

  magick pixel.gif   -morphology Dilate:3 Diamond -scale 800%  k_diamond_3.gif
[IM Output]
これと最初の例の違いに注意してください。「:3」が「Diamond」カーネルの半径から「Dilate」メソッドを使用する回数に変更されているだけです。「*iteration*」を使用して効果的な近傍を大きくすると、「Square」や「Diamond」などのほとんどの「円形」または「凸状」のカーネルで機能します。しかし、**すべてのカーネルタイプで機能するわけではありません**。「Plus」(これは「凹状」ではない)などの非凸状カーネルの場合、非常に異常に結果が生成されます。
たとえば、これは「Plus」(半径2)から2倍のサイズの「Plus:4」カーネルへの移行と同じではありません…

  magick pixel.gif   -morphology Dilate:2 Plus  -scale 800%  k_plus_2.gif
[IM Output]
「*iteration*」回数を「0」に設定すると、形態処理は何もしません。これは、操作を行わせたくないが、コマンドラインから削除したくない場合に操作を「オフにする」ための便利な方法です。別の「0」の反復回数については、以下の詳細出力の表示を参照してください。「-1」の特別な値を使用すると、画像に変更が見られなくなるまで演算が繰り返されます。つまり、画像は「収束」点に達します。ただし、これは危険な場合があります。状況によっては、非常に長時間実行される操作につながる可能性があります。たとえば、「Dilate」などの演算では、画像全体が完全に白で塗りつぶされるまで膨張処理が繰り返されるだけです。基本的に、一種の暴走「塗りつぶし」を生成します(以下の次の例を参照)。より大きな近傍効果を生み出すために「Disk」カーネルを反復処理することも、一般的には推奨されません。つまり、「Disk」カーネルは半径が大きくなるにつれてより正確な円形になるため、反復された円は形状だけでなく、カーネルの誤差(非円形)も拡大します。そのため、反復操作(より歪んだ円を生成する)よりも大きな半径を使用する方が良い場合があります(これは速度が遅くなります)。ただし、「Disk」の半径が非常に大きくなると、半径と複数の反復の組み合わせにより、高速で許容できる結果が生成される可能性があります。具体的な状況に合わせて注意深く実験を行う必要がある場合があります。

変更の詳細出力

形態演算の反復(繰り返し)の結果を確認するには、「-define debug=True」オプションを設定して詳細な操作制御を有効にします。形態演算子が反復処理を行うと、反復の増加する回数と、各反復ステップによって画像のピクセルがいくつ変更されたかが報告されます。出力は標準エラーに出力されるため、画像の結果をパイプで接続することもできます。たとえば、画像全体が白で塗りつぶされ、画像に対してこれ以上変更が行われなくなるまで、より大きな「Octagon」カーネルを使用して単一ピクセル画像を「Dilate」します。「-1」の反復制限は、永遠に、または変更が見られなくなるまで反復することを意味します。

  MAGICK_THREAD_LIMIT=1 \
    magick pixel.gif -define debug=true -morphology Dilate:-1 Octagon \
            -scale 800% iterate_infinite.gif
[IM Output]
[IM Text]
各反復で行われた変更の数に注意してください。最初は20個のピクセルが黒から白に変換されました。次に、次の反復でさらに48個のピクセルが変換されました。この数は、結果の形状のエッジが大きくなるにつれて一般的に増加しますが、形状が画像境界に達すると再び小さくなり始めます。4回目の膨張処理で、最後の4ピクセル(画像の角)が塗りつぶされました。最後の膨張処理(反復5回)では、画像がすでに完全に塗りつぶされていたため、ピクセルに対してこれ以上の変更は行われませんでした。変更が行われなかったため、形態処理は自動的に中止され、操作のこの段階の変更の最終数が表示されます。「-1」の無限反復には内部制限があります。これは現在、画像の最大幅または高さに設定されています。これは、ImageMagickが無限ループに入るのを防ぐために行われます。ただし、通常、操作は内部制限に達するずっと前に終了します。一部の形態処理メソッドは、実際にはより単純で原始的なメソッドの観点から定義されています。たとえば、「Smooth」メソッドは、そのような複合メソッドの1つです。このメソッドを使用する際に生成される「-define」出力には、その処理を構成する複数の内部ステップが表示されます。

  MAGICK_THREAD_LIMIT=1 \
    magick man.gif -define debug=true -morphology Smooth:2 Diamond null:
[IM Text]
ご覧のとおり、「Smooth」は実際にはさらに4つの原始的なメソッドを反復処理するため、要求された操作を実行するために内部的に画像を8回処理します。各行は…で構成されています。
Smooth:i.s
これは、画像に適用される高レベルの形態処理メソッドと、IMが処理している反復回数「i」および原始的な「段階」数「s」を示しています。「Smooth」メソッドの場合、最初の数値は常に「1」です。ユーザーが指定した「反復回数」は、下位レベルの原始メソッドで適用されるためです。他のメソッドでは、ユーザーが指定した反復回数は、下位レベルではなく、この上位レベルで適用される場合があります。2番目の「段階」数は、適用されている原始的な「段階」数です。「Smooth」自体は、4つのこのような段階で構成されています。「Open」と「Close」の複合メソッドを実装しているためです。
Dilate*:i.k
これは、適用されている原始的なメソッドです。最初の数値「i」は、再びユーザーが指定した反復回数です(ここで適用されている場合)。2番目の数値「k」は、原始的な形態処理メソッドによって適用されているカーネルです。カーネルは1つしかないため、この場合は常に0になります。(以下のマルチカーネル処理を参照)「*」は、形態処理の原始的なメソッドによって適用される前に、カーネルが反転(または原点を中心に180度回転)されたことを示しています。これは、一部の複合形態処理メソッドでは必要です。この場合、「Close」メソッドは、「Dilate」と「Erode」の原始的なメソッドの使用において常に反転カーネルを使用します。
#6 => 変更 311 合計 637
これは、形態学プリミティブを画像に適用した結果のレポートです。「ハッシュ」番号は、画像を通過するプリミティブのパスの増加カウントです。これにより、複合形態演算子の計算集約度を把握できます。次に、そのパス中に何らかの方法で変更されたピクセルの実際の数が得られます。これが、特定のプリミティブとカーネルに対する複数回の反復の最後の場合、ピクセル変更の合計カウントも出力されます。ただし、これは開始から終了までの合計で変更されたピクセル数を反映するものではなく、特定のプリミティブ、カーネル操作の低レベルの反復によって引き起こされた変更のみを反映しています。一部のピクセルは、一部の形態学プリミティブによって複数回変更される可能性があります。
上記から、IMは内部的に、与えられた形態学メソッドを完全に処理するために4つの処理ループを適用する可能性があることがわかります。ただし、通常、これらのループの大部分は一度だけ適用されます。
警告:最新のマルチコアマシンでのマルチスレッド環境で実行されているマシンでは、変更されるピクセル数が正しくない場合があります!単一スレッド環境で実行された場合にのみ、正確であることが保証されます。これはバグとして分類されますが、重要なバグではありません。

これが問題の場合は、上記最後の2つの例で行ったように、ImageMagickのその特定の実行に対して環境変数 "MAGICK_THREAD_LIMIT" を '1' に設定してください。

IM v6.8.4 以降は、マルチスレッド環境でもカウントが正しく処理されるため、「MAGICK_THREAD_LIMIT」環境設定は不要になりました。

生成されたカーネルの表示(デバッグ目的)

生成された特定のカーネルを定義するために使用された値を実際に確認したい場合は、特別な設定を定義できます...

    -define morphology:showkernel=1    
    -define convolve:showkernel=1    
上記のいずれかの定義により、カーネルが使用の準備のために完全に処理された後、IMは(「標準エラー」に)生成されたカーネルに関するすべての情報を出力します。(畳み込みカーネルのスケーリングを参照)。たとえば、組み込みの 'Disk' カーネルの実際の値を次に示します...

  magick xc: -define morphology:showkernel=1 -morphology Dilate:0 Disk null:
[IM Text]
カーネルのみを表示したかったため、画像処理は全く気にしません。そのため、形態学の「イテレーション」を「0」(何も実行しない)に設定し、null:出力ファイル形式を使用して画像の結果を破棄しました。上記にある特別な浮動小数点値「nan」は、ユーザー定義カーネルを入力する場合と同じ意味を持ちます。「数値ではない」ことを意味し、近傍の一部ではないカーネルの部分をマークします。これらの値は、すべての形態学演算によって無視されます。別の例を次に示します。今回は「Comet」畳み込みカーネルです。

  magick xc: -define morphology:showkernel=1 -morphology Dilate:0 Comet:0x2  null:
[IM Text]
これは実際には1次元ガウス曲線の半分(シグマ1.0)であり、ImageMagickからそのような曲線を抽出する良い方法を提供できます。また、この特定のカーネルの「原点」(影響を与えるピクセル)は中心からずれている(+0+0にある)ことに注意してください。これはあまり一般的ではありません。出力の値のサイズと間隔は、特別な精度演算制御で制御できます。これは、形態学演算子とほぼ同時にIMに追加されました。たとえば、デフォルトの6桁から3桁に有効桁数を制限するために「-precision」を使用して、前の例を繰り返します。

  magick xc: -define morphology:showkernel=1 -precision 3 \
          -morphology Dilate:0 Comet:0x2  null:
[IM Text]
-precision」オプションは、形態学開発サイクル中にImageMagickバージョン6.5.9-1に追加されました。したがって、形態学が利用可能であれば、精度も利用可能と見なすことができます。

カーネルの画像の生成

カーネルを見ることを容易にするために、膨張または畳み込みを単一ピクセル画像に適用して何が生成されるかを確認する代わりに、「kernel2image」という特別なスクリプトを作成しました。このスクリプトは、正確なカーネルの表示出力を抽出し、それをカーネルの画像に変換します。「kernel2image」スクリプトには、カーネルの生の画像(デフォルト)を出力することから、スケーリング量、ピクセル間のギャップ、モンタージュ、ラベル付け、さらには結果の「カーネル画像」の色付けを指定するまで、多くのオプションがあります。このスクリプトを使用すると、さまざまなカーネルを簡単に表示および理解することができ、これらの例ページに表示されているカーネル画像を生成するために広く使用されています。
たとえば、「Octagon」カーネル画像を生成した方法を次に示します。

  kernel2image -10.1  -m "Octagon"  kernel_octagon.gif
[IM Output]
特別なオプション「-10.1」は、すべてのピクセルをサイズ10ピクセルにスケールするだけでなく、それらのピクセル間に1ピクセルのギャップを含めることを意味します。カーネルが十分にスケールされると、カーネルの「原点」はいくつかの描画された円形でマークされます。「-m」は、抽出された「Octagon」カーネルの識別ラベルとシャドウ効果を使用して画像のモンタージュを作成することを指定します。
そして、ここで、上記で使用した「L」字型のユーザー定義カーネルの「カーネル画像」を生成します。

  kernel2image -20.2 -ml 'L-Shape'  "3: 1,-,-  1,-,-  1,1,- " kernel_lman.gif
[IM Output]
既存の画像からカーネルを作成する場合は、「image2kernel」スクリプトを使用して、画像からカーネルデータファイルを作成できます。このスクリプトは通常グレースケール画像を使用しますが、多色の画像が与えられた場合、画像の各チャネルは個別のカーネルデータファイルに変換されます。
ここでは、小さなフラグ画像(  )からユーザーカーネルデータを作成し、「kernel2image」を使用してそのデータを拡大された「カーネル画像」に変換して表示します。

   image2kernel -qgm flag.gif  flag_kernel.dat
   kernel2image -6.1 -m  -ml "Flag"  @flag_kernel.dat  kernel_flag.gif
[IM Output]
補足:同様のスクリプト「enlarge_image」を使用して小さな画像の「拡大」バージョンをより直接的に生成できましたが、それは画像を表示することであり、カーネルデータ「flag_kernel.dat」を表示したわけではありません。

複数のカーネルリストの処理

複数のカーネルの生成

IM v6.6.2-0 以降、複数のカーネルを指定して、画像に1つずつ適用できます。複数のカーネルを指定するには、セミコロン「;」で区切って各カーネル定義を連結します。最後のセミコロンは省略可能です。たとえば、ここでは、「パターンマッチング」コーナーピクセルに使用できるリストを含む特別なカーネルリストを定義します。

     3: 0,0,- 0,1,1 -,1,-  ;      
     3: -,0,0 1,1,1 -,1,-  ;
     3: -,1,- 1,1,0 -,0,0  ;
     3: -,1,- 0,1,1 0,0,-  ;
余分なセミコロン(「;」)は、カーネルの仕様間に少なくとも1つあれば問題ありません。カーネルの仕様に余分な空白(改行を含む)があっても問題ありません。この定義のカーネル出力の表示を次に示します。

  magick xc: -define morphology:showkernel=1 -morphology Dilate:0 \
             " 3: 0,0,- 0,1,1 -,1,-  ;
               3: -,1,- 1,1,0 -,0,0  ;
               3: -,0,0 1,1,1 -,1,-  ;
               3: -,1,- 0,1,1 0,0,-  ; " null:
[IM Text]
そして、特別な「kernel2image」スクリプトを使用して、これらの4つのカーネルのカーネル画像を次に示します。

   kernel2image -20.2 -ml '' -mt x1 \
             " 3: 0,0,- 0,1,1 -,1,-  ;
               3: -,1,- 1,1,0 -,0,0  ;
               3: -,0,0 1,1,0 -,1,-  ;
               3: -,1,- 0,1,1 0,0,-  ; "  kernel_multi.gif
[IM Text]
この定義は実際には、90度ずつ回転させた4つのカーネルのセットを形成するように拡張された、1つのカーネルで構成されています。補足:この定義は、特別な「Corners」パターンマッチングカーネル(下記参照)とほぼ同等ですが、実際の形状のコーナーに限定されており、コーナー、背景、または前景ではありません。

回転したカーネルリストへの展開

IM v6.2.2-0 以降、3つの特別なフラグのいずれかを使用して、名前付きまたはユーザー定義のカーネルで、単一のカーネルを回転されたカーネルのリストに展開するように要求できます。3つの特別なフラグは次のとおりです...
'@'    3x3カーネルを45度刻みで循環的に回転させ、最大8つの回転カーネルのリストを生成します。(ニーモニック:「@」は円形です)。
'>' (正方形または線形カーネルのみ)を90度刻みで回転します。(ニーモニック:「>」は直角です)。
'<' 90度回転も生成しますが、「ミラー」シーケンス(回転角度0、180、-90、+90)で生成します。この特別な形式の回転展開は、「Thinning」などの形態学メソッドでより適切に機能します。(ニーモニック:「<」は直角のミラーです)。
たとえば、上記の同じカーネルは、より簡単に次のように指定できます...

    ' 3>:  0,0,-  0,1,1  -,1,- '
これは1つのカーネルを定義し、「>」フラグはIMに90度回転したリストに展開するように指示します。そして、結果のマルチカーネルリストの画像を次に示します。

   kernel2image -20.2 -ml '' -mt x1 \
                '3>: 0,0,- 0,1,1 -,1,- '  kernel_rotated_list.gif
[IM Text]
そして、ここで、3x3カーネルを「循環」45度回転で回転させて、8つのカーネルのリストに展開します。

   kernel2image -20.2 -ml '' -mt x1 \
                '3@: -,1,- -,0,- 1,1,1 '  kernel_rotated_list2.gif
[IM Text]
同じフラグをそれらのカーネルの引数セクションで使用して、任意の「単一」組み込み名前付きカーネルIMに対して同じ操作を行うこともできます。たとえば、ここでは、対称的な「Blur」カーネルを取り、「>」フラグを使用して90度回転したリストに展開します。

   kernel2image -12.1 -n -ml ''   "Blur:0x1>"  blur_kernels.gif
[IM Text]
3番目のカーネルは最初のカーネルを正確に再現するため、2つのカーネルしか生成されませんでした。これは検出され、回転カーネルの生成は停止します。ただし、「原点」が中心からずれている場合、カーネルの「形状」は一致するものの、原点の位置は同じではないため、4つの回転カーネルの完全なシーケンスが生成されます。多くの組み込みカーネル定義は、マルチカーネルリストを自動的に生成するため、その目的でフラグを指定する必要はありません。つまり、回転展開は特定のカーネル定義にも「組み込み」されています。このようなカーネルは通常、元の単一カーネル定義の「サブタイプ」も提供するため、特定の目的に特定のカーネルを選択できます。

複数のカーネルの結果マージ:再反復または合成

複数のカーネルを定義した場合、形態学メソッドは、複数のカーネルによって生成された結果をどのようにマージする必要があるかについても認識する必要があります。これは、グローバル定義を使用して制御できます...

    -define morphology:compose={compose_method}    
ほとんどの形態学メソッドのデフォルトは「None」の設定です。これは、指定された形態学メソッドを使用して各カーネルが適用された後、結果の画像を次のカーネルのソースとして使用する必要があることを意味します。つまり、単に「再反復」するか、適用された1つのカーネルの結果を次のカーネルで再利用します。たとえば、2つの90度回転した「Blur」カーネルを使用して畳み込みを行うと、次のようになります。

  magick pixel.gif  -morphology Convolve "Blur:0x1>" \
          -auto-level  blur_re-iterate.gif
[IM Output] * [IM Output] , [IM Output] ==> [IM Output]
ご覧のとおり、両方のカーネルが画像に1つずつ適用されているため、各カーネルは前のカーネルの結果で動作します。つまり、シーケンスで1つのカーネルの結果を次のカーネルで「再反復」します。これは、次の2つの手順を実行することと同等です。

  magick pixel.gif -morphology Convolve "Blur:0x1" -auto-level blur_1.gif
  magick blur_1.gif -morphology Convolve "Blur:0x1+90" \
          -auto-level blur_re-iterate.gif
[IM Output] * [IM Output] ==> [IM Output] * [IM Output] ==> [IM Output]
実際、これはぼかし演算子が画像のぼかしをより迅速に生成するために実際に機能する方法です。ガウスカーネルとぼかしカーネルを参照すると、この使用方法がより詳細に示されています。
{compose_method}」を「None」以外のメソッドに設定すると、操作は「再反復」されません。代わりに、各カーネルは「元の画像」に適用され、結果の画像は指定された「{compose_method}」メソッドを使用して合成されます。たとえば、「Lighten」形態学メソッドを使用して、個々の結果の和集合を生成すると、次のようになります。

  magick pixel.gif -define morphology:compose=Lighten \
                     -morphology Convolve "Blur:0x1>" \
          -auto-level blur_union.gif
[IM Output] * [IM Output] , [IM Output] ==> [IM Output]
これは次のことを行うことと同等です。

  magick pixel.gif -morphology Convolve "Blur:0x1"  -auto-level blur_1.gif
  magick pixel.gif -morphology Convolve "Blur:0x1+90" -auto-level blur_2.gif
  magick blur_1.gif blur_2.gif -compose Lighten -composite \
          -auto-level blur_union.gif
[IM Output] * [IM Output] ==> [IM Output]
[IM Output] * [IM Output] ==> [IM Output]
[IM Output] U [IM Output] ==> [IM Output]
形態学中にIMが実際に行っていることがわからない場合は、変更の詳細出力をオンにします。たとえば、各カーネルで再反復した詳細出力を次に示します。

  magick pixel.gif -define morphology:compose=None \
         -define debug=true -morphology Convolve "Blur:0x1>" null:
[IM Text]
そして、各カーネルの結果の和集合(Lighten合成)の詳細出力を次に示します....

  magick pixel.gif -define morphology:compose=Lighten \
         -define debug=true -morphology Convolve "Blur:0x1>" null:
[IM Text]
いずれも、ImageMagickが最終画像を生成するために実行している処理を明確に示しています。小数点以下の数値は、各ステップで適用されているカーネル番号を表します。最後に、'morphology:compose'設定に従って画像をどのように合成するかが続きます。多くの数学的合成方法とその同等の集合論タイプの演算を使用して、各カーネルを元の画像に適用した結果をマージすることもできます。要約すると、この設定は、マルチカーネルリストの個々のカーネルを指定された画像にどのように適用するかを定義します。デフォルトは'None'の合成値で、単に結果を「繰り返し処理する」ことを意味します。それ以外の場合は、指定された合成方法に基づいてすべての結果をマージします。

基本的な形態学的方法

形態学的方法は、画像内のオブジェクトの形状を見つけて分析するための画像処理技術です。拡大、縮小、特定の形状の特定などを行います。もともとバイナリ(純粋な白黒)画像を念頭に置いて開発されたため、最も一般的には閾値処理された単純な白黒の形状を含む画像に適用されます。慣例により、バイナリ画像の白は前景を表し、黒は背景を表します。したがって、メソッド名は、この慣例に従って記述されています。つまり、演算子がグレースケール画像、または場合によってはカラー画像で機能しないという意味ではありませんが、元の目的はバイナリの形状を処理することでした。上記の形状カーネルは、形態学的方法で最も一般的に使用される近傍を定義する「形状」です。このようなカーネルは、通常、画像内の形状の構造を決定するために使用されるため、「構造要素」と呼ばれることがよくあります。

浸食  ( )

名前が示すように、「Erode」メソッドは、背景ピクセルから白い形状を「侵食」して小さくします。画像の黒い領域を拡大していると考えることもできます。「八角形」カーネルを使用して浸食された単純なバイナリ「人型」形状を次に示します。

  magick man.gif   -morphology Erode Octagon  erode_man.gif
[IM Output] - [IM Output] ==> [IM Output]
その基本的な効果は、画像に存在する可能性のある突起や点を細くしたり、完全に削除したりすることですが、画像に存在する穴(この画像の「腕」によって引き起こされたものなど)も大きくします。一般的に、カーネルのサイズは、削除されるピクセル数を決定します。

膨張  ( )

Dilate」メソッドは、「Erode」の双対です。指定されたカーネル(および反復回数)に従って白い形状を拡大し、形状を大きくします。もちろん、画像の黒い領域を「侵食」することも意味します。

  magick man.gif   -morphology Dilate Octagon  dilate_man.gif
[IM Output] + [IM Output] ==> [IM Output]
形状が大きくなるだけでなく、輪郭が滑らかになることに注意してください。「脚」の間の大きな凹みは埋められ、画像に含まれていた小さな単一ピクセルの「穴」も埋められました。カーネルのサイズと形状は、画像の端の周りに追加されるピクセル数を決定します。
Dilate」と「Erode」は双対です。つまり(少なくとも対称カーネルの場合)、形態学的方法を適用する前後に画像を反転することで、実際にはもう一方の演算子を実行します。たとえば、ここでは、「反転された画像」に対して「Dilate」を使用して侵食を実行します。

  magick man.gif -negate \
             -morphology Dilate Octagon   -negate dilate_man_neg.gif
[IM Output]

開口  ( )

今回は、はるかに大きい「円盤」カーネルを使用して、「Open」メソッドの効果を示します。

  magick man.gif   -morphology Open Disk  open_man.gif
[IM Output] o [IM Output] ==> [IM Output]
その結果、「Open」は、鋭い点を丸めて輪郭を滑らかにし、使用された形状よりも小さい部分を削除することがわかります。また、細い橋を切断したり「開いたり」もします。ただし、画像に存在する可能性のある「穴」や隙間(形状の「脚」の間など)は削除されません。また、形状の基本的な「コア」のサイズを大きくしたり小さくしたりもしません。実際のところ、これは画像を「侵食」してから、提供されたのと同じカーネルを使用して「膨張」します。

  magick man.gif         -morphology Erode  Disk  open_erode.gif
  magick open_erode.gif  -morphology Dilate Disk  open_man_2.gif
[IM Output] ==> [IM Output] ==> [IM Output]
同じカーネルで既に開かれている形状に対して「Open」を実行しても、形状はそれ以上変化しません。たとえば…

  magick open_man.gif  -morphology Open Disk  open_man_twice.gif
[IM Output] ==> [IM Output] ==> [IM Output]
つまり、「Open」操作を同じカーネルで繰り返しても、結果は変わりません。
このため、提供された反復回数は、メソッド全体ではなく、個々の膨張と侵食のサブメソッドに適用され、反復を使用して有効なカーネルを「拡大」するために使用されます。つまり、「Open:2」の反復は、実際には画像に対して「Erode:2」を実行してから「Dilate:2」を実行します。これにより、カーネルによって定義される有効な「近傍」が大きくなります。

  magick man.gif   -morphology Open:2  Disk  open_man_x2.gif
[IM Output]
ここでは、結果として得られるより大きな近傍により、男性の「頭」と「足」の先端部が削除されていることがわかります。形状の本体は基本的に無傷ですが、外観も滑らかになっていますが、脚の間の隙間はそのまま残っています。これは、カーネルのサイズを2倍にした場合と同じ効果ですが、その正確な形状は半径の2倍のカーネルとまったく同じではない可能性があります。

閉包  ( )

Close」メソッドの基本的な用途は、カーネル「構造要素」のサイズ程度の「穴」や「隙間」を減らすか削除することです。つまり、その程度のサイズの背景の部分を「閉じる」ことです。

  magick man.gif    -morphology Close Disk   close_man.gif
[IM Output] . [IM Output] ==> [IM Output]
この演算子の基本的な効果は、穴や凹みを埋める(閉じる)ことによって形状の輪郭を滑らかにすることです。また、カーネルが同時に両方に触れるのに十分近い他の形状に接続する「橋」を形成します。しかし、形状の基本的な「コア」のサイズを大きくしたり小さくしたりすることはありません。実際のところ、これは画像を「膨張」してから、提供されたのと同じカーネルを使用して「侵食」します。これにより、画像が最初に大きくなり、次に小さくなります。「開口」とは逆の順序です。

  magick man.gif           -morphology Dilate Disk  close_dilate.gif
  magick close_dilate.gif  -morphology Erode  Disk  close_man_2.gif
[IM Output] ==> [IM Output] ==> [IM Output]
その結果、画像の外側の点はそのまま残りますが、「湾」は滑らかになり厚くなり、「穴」と「隙間」は閉じられます。「開口」と同様に、同じカーネルで「閉包」メソッドを繰り返しても、画像にはそれ以上の変更は加えられません。ただし、演算子に「反復」を使用すると、内部のサブメソッドが繰り返されるため、より大きなカーネルを使用する場合と同様に、より強い丸め効果が得られます。
膨張」と「侵食」メソッドと同様に、「開口」と「閉包」メソッドは双対です。演算の前後に画像を反転することで、もう一方の「双対」の効果を再現できます。

  magick man.gif   -negate -morphology Close Disk -negate   close_man_neg.gif
[IM Output]

平滑化

Smooth」メソッドは、形状の「開口」に続いて「閉包」を適用します。これにより、最初に「小さなオブジェクト」が削除され、次にカーネル「構造要素」のサイズ程度の「穴」または「隙間」が埋められます。ここでは、中程度の「八角形:3」カーネルを使用して画像を平滑化します。

  magick man.gif  -morphology Smooth  Octagon:3  smooth_man.gif
[IM Output]
ご覧のとおり、「凹み」、「隙間」、「穴」、「点」はすべて、カーネルのサイズと形状に従って滑らかになり、丸められています。「Smooth」演算子は、ゆっくりとサイズが大きくなる構造要素を繰り返し使用して、画像からノイズをゆっくりと削除するためにも使用されます。削除された部分を保存すると、画像の形態学的「分解」が得られ、さらに研究に使用できます。下記の粒度を参照してください。この方法は、スキャンされたドキュメントのクリーニングに特に適しています。これは、元の画像に4つの別々の「プリミティブ」演算を実際に適用していることに注意してください。したがって、「侵食」や「膨張」よりも4倍遅くなります。

フラットグレースケール形態学

基本的な形態学的方法の4つのうち本質的にすべてと、これら4つの方法で定義される後続の方法は、バイナリ画像で動作するように特に設計されていますが、グレースケール画像とカラー画像の両方に適用できます(ただし、カラー画像では奇妙な色の効果が発生する可能性があります)。グレースケール演算の実用的な例をここに示す必要がありますただし、カーネル自体は常に単純な「オン」または「オフ」の近傍と見なされます。「nan」または「0.5」未満のカーネル値は、定義する「近傍」の外側にあると見なされます。要約すると、上記の演算子は、「高さ」または「3次元」の特徴のない「フラット」カーネルを適用しますが、グレースケール画像にも適用できます。

真のグレースケールまたは3次元形態学

真のグレースケールまたは3次元形態学(あるライブラリがそう呼んでいるように)は、結果として最大/最小値を探す前に、画像内の隣接ピクセルからカーネルに見つかった値を実際に加算または減算します。これは、グレースケール画像を3次元形態学オブジェクトの「高さフィールド」として扱い、グレースケール形状のカーネルをその高さフィールドを調整する平滑化形状として扱います。真のグレースケール形態学の実装の詳細については十分に文書化されていますが、実際的な状況での使用については文書化されていません。つまり、「フラットな形状のカーネル」以外の真のグレースケール形態学の使用例は見つかっていません。「測光」処理での使用に関するコメント以外です。このため、真の3次元グレースケール形態学を実装していません。ただし、実際そのようなフラットではないグレースケール形態学演算子が必要な場合はお知らせください。適切な演算子を実装します。下記の特別な「距離」メソッド(下記参照)は、最小の「最小」値を取得する前に、各ピクセル値にカーネルの値を追加するという点で、真のグレースケール形態学の動作と実際によく似ています。ただし、このメソッドは3D侵食(減算して最小値を取得)または膨張(加算して最大値を取得)形態学の定義のいずれにも一致しません。ただし、非常に密接に関連しており、おそらくこれらのメソッドを使用して実装できます。

カラー画像の強度バリアント

上記の4つの方法は、グレースケールのチャンネルメソッドであるため、カラー画像に適用すると、あるチャンネルだけが変更され、他のチャンネルは変更されないことで、色ずれが発生する可能性があります。これらのメソッドは、グレースケール画像とバイナリ画像での使用を意図しており、マルチチャンネルカラー画像には適していません。その結果、カラー画像では色が歪み、演算に応じて明るくなったり暗くなったりします。これを踏まえ、これらのメソッドの「Intensity(強度)」バージョンである「ErodeIntensity」、「DilateIntensity」、「OpenIntensity」、「CloseIntensity」を作成しました。これらは、定義された「近傍」内のピクセルを比較し、ピクセルの強度に応じて現在のピクセルの色を置き換えます。つまり、個々のチャンネル値ではなく、カラーピクセル全体がコピーされます。その結果…
Intensityバリアントは、画像に新しい色を生成しません。
本質的にIntensityメソッドは、現在の"-channel"設定を完全に無視します。例えば、ここでは組み込みの"rose:"画像に、「Dilate」モーフォロジー(明るい領域を拡大)のバイナリとIntensityバリアントを使用します。

  magick rose: -morphology Dilate          Octagon:3  rose_dilate.gif
  magick rose: -morphology DilateIntensity Octagon:3  rose_dilate_intensity.gif
[IM Output] ==> [IM Output] [IM Output]
ご覧のように、通常の「Dilate」メソッドでは、各チャンネルが個別に処理されるため、拡大された大きなスポットそれぞれに異なる色合いが生じる可能性があります。しかし、2番目のIntensity dilationは、最も明るいスポットの完全な色を保持し、ブールカーネル形状に従ってそれらを拡大します。Intensityメソッドには、「Intensity」という単語を「I」に置き換える簡略表記もあります。「CloseIntensity」メソッドを使用する例では、「CloseI」という簡略名を使用します。例えば、以下は、組み込みのrose画像に4つのIntensityバリアントをそれぞれ適用した結果です。

  magick rose: -morphology ErodeI Octagon:3 rose_erode_intensity.gif
[IM Output]


magick rose: -morphology DilateI Octagon:3 rose_dilate_intensity.gif
[IM Output]

  magick rose: -morphology OpenI Octagon:3 rose_open_intensity.gif
[IM Output]

  magick rose: -morphology CloseI Octagon:3 rose_close_intensity.gif
[IM Output]
最後の2つは、ペイントオペレーターの代替オペレーターとして特に適している可能性があります。これらのメソッドは実験的なものとして分類されており、使用方法に関するコメントや問題点があれば歓迎します。コメントがなければ、これ以上の追加は行いません!

代替の基本的な形態学的手法

For people with versions of IM older than v6.5.9-0 you can still implement
some basic morphology methods.

You can generate a kernel that is all ones. For example a 7x7 array of 1's
(radius=3), by use an extremely large sigma and specify the appropriate radius,
using a Gaussian blur.

As such
    -convolve 1,1,1,1,1,.....
for a total of 49 ones is equivalent to
    -gaussian-blur 3x65535

This allows you to generate a simple square kernel for binary morphological
methods.

'Dilate'   for a 3x3 square kernel (radius=1) is thus
    -gaussian-blur 1x65535 -threshold 0
'Erode'  is thus
    -gaussian-blur 1x65535 -threshold 99.999%

As previously shown above
'Open' is a 'Dilate' followed by a 'Erode'
'Close' is a 'Erode' followed by a 'Dilate'
and Smooth is a 'Open' followed by a 'Close'

Larger square kernels can be specified using larger radii.

Unfortunately the other built-in kernel shapes are not available,
without using the convolve operator to manually define their shape.

This also only truly works for binary morphology. To implement a
flat-greyscale morphology, you will need to use a different technique of
generating a separate image for each pixel in the kernel, and rolling
it for the pixels position.

Both the thresholded-convolve and roll-shift composition methods have been
implemented in Fred Weinhaus's script "morphology", which was created long
before the "-morphology" operator was added to ImageMagick.

See and Download Fred's Weinhaus "Morphology" Script from
  http://www.fmwconcepts.com/imagemagick/morphology/index.php

差分モーフォロジーメソッド

次のレベルのモーフォロジーメソッドは、差分モーフォロジーと呼んでいます。つまり、これらのモーフォロジーメソッドの結果は、以前の基本的なモーフォロジーメソッドのいずれかと元の画像、または他のモーフォロジーメソッドとの差です。本質的に、それらは、より単純なメソッドによって元の画像に加えられた変更を返し、画像間の輪郭、追加、または削除を示します。それらは本質的に、画像結果の「Difference」または「Minus」画像合成です。

EdgeIn

EdgeIn」メソッド(内部勾配とも呼ばれます)は、Erosionによって元の画像から削除されたピクセルを見つけます。その結果、エッジに最も近いピクセルで、元の形状の一部であったピクセルが返されます。

  magick man.gif   -morphology EdgeIn Octagon  edgein_man.gif
[IM Output] ==> [IM Output] ==> [IM Output]
結果のエッジは、与えられたカーネルの約半分です。「Octagon」カーネルの場合はかなり厚くなります。通常は、形状の1ピクセルの輪郭を作成するために、はるかに小さい「Diamond」または「Square」カーネルを使用します。「EdgeIn」をアルファチャンネルで使用してエッジピクセルを抽出する例は、Sparse Color as a Fill Operatorに示されています。

EdgeOut

EdgeOut」メソッド(外部勾配とも呼ばれます)は、その画像のDilationによって元の画像に追加されたピクセルを見つけます。その結果、形状のすぐ隣にある背景ピクセルが返されます。

  magick man.gif   -morphology EdgeOut Octagon  edgeout_man.gif
[IM Output] ==> [IM Output] ==> [IM Output]
EdgeOut」をアルファチャンネルで使用した例は、Outline or Halo Transparencyに示されています。

Edgeまたはモーフォロジー勾配

Edge」メソッドは「モーフォロジー勾配」を返し、これは最後の2つの「エッジ」メソッドの追加、より具体的にはErosionされた形状とそのDilationされた形状の差として説明できます。

  magick man.gif   -morphology Edge Octagon  edge_man.gif
[IM Output] ==> [IM Output] ==> [IM Output] ==> [IM Output]
前述のように、カーネルのサイズと形状によって、侵食された画像の厚さが決まります。その厚さは、本質的にカーネルサイズから中心ピクセルを引いたものと等しくなります。したがって、半径3のカーネルは一般的に6ピクセルの厚さの「Edge」を生成します(カーネルサイズは7ピクセルの厚さ)。
例えば、最小の「Diamond」カーネルを使用した形状の「Edge」輪郭を示します。

  magick man.gif  -morphology Edge Diamond  man_outline.gif
エッジは2ピクセルの厚さであり、元の形状の実際の「ピクセルエッジ」の両側に位置するピクセルが含まれています。このエッジをより薄くする唯一の方法は、画像全体を対角線方向に半ピクセルオフセットすることです。
[IM Text]
さまざまな方法で形状の輪郭を取得する方法の詳細については、Edge Detectionのセクションを参照してください。今後の予定:'対角線'を使用したエッジの生成。

Top-Hat

TopHat」メソッド(より具体的には「ホワイトトップハット」)は、形状のOpeningによって削除されたピクセルを返します。つまり、点を丸めるために削除されたピクセルと、形状間の接続されたブリッジです。

  magick man.gif   -morphology TopHat Disk  tophat_man.gif
[IM Output] ==> [IM Output] ==> [IM Output]
ご覧のように、ピクセルは多くの場合、使用されたカーネルよりも厚いピクセルセットのない、非常に離散的な小さな島を形成します。メソッド名「Top Hat」は、実際には、私たちが行ったようにバイナリ画像ではなく、グレースケール3次元モーフォロジーでメソッドを適用した場合のオペレーターの使用を指します。このオペレーターは、グレースケール画像でより一般的に使用されます。今後の予定:グレースケールトップハットの例

Bottom-Hat

BottomHat」メソッド(ブラックトップハットとも呼ばれます)は、形状のClosingによって画像に追加されたピクセルです。つまり、「穴」、「ギャップ」、「ブリッジ」を埋めるために使用されたピクセルです。

  magick man.gif   -morphology BottomHat Disk  bottomhat_man.gif
[IM Output] ==> [IM Output] ==> [IM Output]
繰り返しますが、それはまた、使用されたカーネルよりも厚くない、非常に離散的な「島」のピクセルをもたらすことがわかります。しかし、それらは常に、以前のメソッドとは完全に異なる島々の集合です。今後の予定:グレースケールボトムハットの例

低レベルモーフォロジーメソッドの使用

基本的な形態学とチャンネル

上記の基本的なモーフォロジーメソッドはすべてチャンネルメソッドであるため、現在の"-channel"設定に従って、画像の個々のチャンネルに適用されます。これは、定義されていない透明領域からの「カラーリーク」をあまり気にしない限り、カラー画像にこれらのメソッドを適用できることを意味します。例えば、元の「男性の姿」画像のアルファチャンネルを「Erode」して、カラーチャンネルを変更せずに処理してみましょう。

  magick figure.gif -channel A  -morphology Erode Diamond:3 \
          +channel   figure_erode.gif
[IM Output] - [IM Output] ==> [IM Output]
ご覧のように、うまく機能します。他の例については、Sparse Color as a Fill Operator(画像のエッジピクセルを見つけるために「EdgeIn」メソッドを使用)とOutline or Halo Transparency(特定の色で画像のエッジを拡大するために「EdgeOut」を使用)を参照してください。

特定の形状の検索

Knowledge about an object depends on the manner in which we probe (observe)
it.                    -- Georges Matheron, The Father of Morphology

Using Erode to locate specific shapes from a large correction of shapes. Taken
to extreme this creates Skeletons, see also Thinning Skeletons.

Restoring objects using Open (smoothed result) or Conditional Dilation.

Needs some sort of Connected Component Analysis, (Segmentation) to properly
count objects found within an image.

形状の集合の粒度

ゆっくりとサイズが大きくなる構造要素の画像で一連の「Open」操作を行い、結果の面積を測定することで、画像に見られるそのような形状の数をすばやく要約できます。その結果の導関数(傾き)をとると、画像を形成する形状の数とサイズに関する「スペクトル」が得られます。このグラフは、特定の形状に対する画像の「粒度」です。Granulometry (morphology), Wikipediaを参照してください。サイズごとの違いにより、サイズに基づいて特定の要素を分離して数えることができ、順番に異なるサイズと形状の要素を含む領域を分離することもできます。その結果、テクスチャセグメンテーションの方法になります。形状の集合の数とサイズを決定するデモ。ただし、完全に実装するには「カウント」メソッド(追加予定)が必要です。歴史的注釈…この用途は、実際には、1960年代のパリの鉱山会社でのモーフォロジーメソッドの最初の作成の原動力でした。これにより、作成者は、鉱物サンプルの顕微鏡写真にある穀物構造を分析して採掘の適性を決定する自動化システムを作成できました。つまり、サンプル内の鉱物のサイズと量を特定して数えます。例:2つの鉱石が同じ量の目的の鉱物(通常は岩石中の穀物または結晶として)を持っている場合がありますが、より大きな穀物を持つ鉱石のみが効果的に採掘できます。これは、周囲の鉱石を含む岩石から大きな純粋な鉱物をより簡単に分離できるためです。これは非常に労働集約的なタスクであり、モーフォロジーによってはるかに容易になりました。

非対称カーネル効果(基本メソッドテスト)

非対称なカーネルを使用してこれらの基本メソッドがどのように機能するかを見てみましょう。たとえば、ここでは、ユーザー定義の「L」形状を特別なモーフォロジーツテスト画像(個々のピクセルを表示するために拡大)に適用します。

  for method in  erode dilate open close; do
    magick test_morphology.gif \
             -morphology $method  '2x3+1+1: 1,-  1,-  1,1 '  test_$method.gif
  done
[IM Text]
その結果は次のとおりです…

[IM Text] Erodeの結果は、カーネル形状と完全に一致するものが、一致点「原点」に単一の白ピクセルになります。また、単一のピクセルの「穴」を、同じ形状に「反転」して拡大します。つまり、カーネルが180度回転したかのように。

[IM Text] Dilateは予想どおり、画像またはカーネルの「負」で「反転」した形式に対して同じ結果を生成します。単一の白ピクセルがカーネル形状に拡大され、一致する「反転」形状の穴は、単一のピクセルの「穴」に縮小されます。
上記の基本的な形態学的処理を適用した結果、テスト画像の正と負の半分の境界が移動することも注目してください。それは予想されることです。これにより、これら2つの方法に関する特定の点が明らかになります。「Erode」メソッドを「Dilate」に変換したり、その逆を行うには、前後の画像を反転するだけでなく、カーネルを原点を中心に回転または反転する必要があります。通常、この2番目の側面は無視できます。ほとんどのカーネルは「対称的」だからです。ユーザー定義の非対称カーネルを使用する場合にのみ重要になります。[IM Text] 前述のように、Openは一般的に画像の「穴」を取り除くことはありませんが、完全に一致する形状は変更されません。大きな形状(テスト画像の負の半分など)も残る可能性がありますが、わずかに変更される可能性があります。
[IM Text] Closeは前の処理の完全な反転の結果ですが、カーネルの反転を必要とせず(内部定義によって反転されるため)、画像の反転のみが必要です。

ヒットアンドミス(HMT)パターンマッチング

ヒットアンドミス( )

Hit-And-Miss」形態学メソッドは、コンピュータサイエンスの文献では一般に「HMT」としても知られており、画像内の特定のパターンを検出して位置を特定するために特別に設計された高度な形態学メソッドです。「原点」周辺の「前景」と「背景」のピクセルの特定の構成を探します。
IM v6.6.9-4以降では、「HitAndMiss」、「Hit_N_Miss」、または単に「HMT」、およびそのバリエーションのいずれかのメソッド名を使用して、この形態学メソッドを指定できます。このバージョン以前は、「HitAndMiss」メソッド名のみを使用できました。
たとえば、「前景」ピクセルで、そのすぐ右に「背景」ピクセルがあるものを探すことができます。

  magick man.gif   -morphology Hit-and-Miss '2x1:1,0'  hmt_right.gif
[IM Output] o [IM Output] ==> [IM Output]
ご覧のように、2要素の小さなカーネルは、画像の右側にあったピクセルのみと一致しました。つまり、このメソッドは、指定されたパターンに一致する特定のピクセルのみを返しました。使用される「カーネル」または「構造要素」には、3種類の要素のパターンのみを含めることができます。「1」は「前景」、「0」は「背景」、そして「Nan」、「-」、または「0.5」の値で指定できる3番目の要素は、「気にしない」または「任意のピクセル」を意味します。「原点」に使用する値は非常に重要です。前景の形状のみを「ヒット」したいか、背景パターンを「ヒット」したいかを定義するためです。しかし、「原点」の値を「気にしない」に具体的に設定した場合、正しい周辺近傍を持つ前景と背景のピクセルの両方に一致させることができます。たとえば、次のような構造要素を使用した場合…

  magick man.gif   -morphology Hit-and-Miss '3x1:1,-,0'  hmt_right2.gif
[IM Output] o [IM Output] ==> [IM Output]
内側と外側のいずれかの右端のピクセルが得られます。そのため、形状境界の両方をマークし、幅2ピクセルのエッジを抽出しています。ただし、すべてピクセルがパターンに一致するわけではないため、すべてのピクセルが倍になるわけではありませんが、一般的にはそれが得られます。「原点」に「気にしない」値を使用することは、後述するThickenメソッドとThinningメソッド(ピクセルの追加または削除に限定される)で特に一般的です。「気にしない」ことで、同じカーネル定義をどちらの操作にも使用できます。操作自体が、関心のある「ヒット」の種類を定義するためです。
別の例を示しますが、今回は「ヒット」を形状の内側にあり、北西を向いた角を形成するピクセルに限定します。

  magick man.gif   -morphology HMT "3:0,0,- 0,1,1 -,1,-" hmt_nw_corner.gif
[IM Output] o [IM Output] ==> [IM Output]
>」フラグを追加することでこの単一の角を90度回転した角のセットに拡張することにより、形状内に現れるすべての角を見つけることができます。

  magick man.gif  -morphology HMT "3>:0,0,- 0,1,1 -,1,-" hmt_corners.gif
[IM Output]
[IM Output]
ご覧のように、「Hit-And-Miss」メソッドは、提供されたカーネルパターンのいずれかに一致するすべてのピクセル位置を検出して返します。
上記の「-morphology」操作の詳細出力を調べると、「Hit-And-Miss」は「Lighten」合成メソッドを使用して、提供されたパターンカーネルのそれぞれに一致するすべてのピクセルの「和集合」を作成することがわかります。

残念ながら、「変更された」ピクセル数は、各カーネルの適用によってオフになったすべてのピクセル数です。言い換えれば、形状内のピクセル数から、各カーネルによって一致したピクセル数を引いた数です。

ヒットアンドミス法をその結果自体で繰り返しても、通常は役に立ちません。画像は大きく変化するため、おそらく後で一致するものがない状態になるからです。

ご覧のように、結果を使用して元の画像を変更し、わずかに異なる画像を生成できます。
具体的に興味のあるものをより選択的にするカーネルのセットを使用できます。たとえば、3本の線が交わる点に関心があるとします。この目的のために特別に設計された「LineJunctions」カーネルセットを使用できます。

  magick lines.gif -morphology HMT LineJunctions hmt_junctions.gif
[IM Output] ==> [IM Output]
ご覧のように、そのセットのカーネルのいずれかに一致する場所はほんのわずかです。ただし、結果によっては、元の画像で一致した場所を実際に確認するのが非常に難しくなる可能性があります。これは、グレースケール画像を処理している場合に特に問題になります。1つの解決策は、「Dilate」を使用して「Ring」などの形状カーネルで一致を拡張することです。たとえば…

  magick lines.gif \( +clone \
             -morphology HMT LineJunctions \
             -morphology Dilate Ring \
             -background red -alpha shape \
          \) -composite              hmt_junctions_rings.gif
[IM Output]
これで、この特定のカーネルセットが3本以上の線の接合部を見つけた場所がはっきりとわかります。「LineJunctions」の各カーネルは、いくつかの特定の場所のみに一致する可能性があるため、このようにパターンマッチングを行うと速度が遅くなる可能性があります。それでも、非常に正確で、非常にうまく機能します。もう1つの同様の「Hit-And-Miss」カーネルセットは「LineEnds」カーネルであり、画像内のすべての線の自由端を見つけるために使用できます。

  magick lines.gif \( +clone \
             -morphology HMT LineEnds \
             -morphology Dilate Ring \
             -background red -alpha shape \
          \) -composite                  hmt_lineends_rings.gif
[IM Output]
HitandMiss - 前景ピクセルのみ -> erodeHitandMiss - 背景のみ -> 反転されたdilate

グレースケール画像でのヒットアンドミス

Hit-And-Miss」メソッドをグレースケール画像に適用すると、返される実際の値は、最小の「前景」値と最大の「背景」値の差になります。負の結果が発生した場合(計算なし)、負の値には実際の意味がないため、「0にクリップ」されます。言い換えれば、「最小の分離」値が2つのピクセルセット間で返されます。ブール形状の場合、それは「0.0」(黒)または「1.0」(白)のいずれかになります。しかし、グレースケール画像の場合、これは一致するピクセルの「勾配」に相当します。たとえば、特定の前景と背景の間にあるパターンの一致におけるコントラストの度合いを識別するために使用できます。グレースケール画像のパターンに実際に一致するピクセルのブール(オン/オフ)の結果のみが必要な場合は、コマンドの後に「-threshold 0」オプションを追加する必要があります。

Thicken (形状へのピクセルの追加)

Thicken」メソッドは、一致する場所ごとに元の形状にピクセルを追加します。たとえば、ここでは、形状の右端から2ピクセル離れた背景ピクセルを探します。

  magick man.gif   -morphology Thicken '3x1+2+0:1,0,0'  thick_right.gif
[IM Output] o [IM Output] ==> [IM Output]
ご覧のように、形状の元の境界の外側にピクセルのラインができました。「Thicken」メソッドを数回繰り返すことで、シーケンスを継続できます。

  magick man.gif   -morphology Thicken:4 '3x1+2+0:1,0,0'  thick_right2.gif
[IM Output]
ただし、ピクセルが追加されているため、パターンマッチングカーネルの原点は「前景」ピクセルと一致しないようにする必要があります。そうしないと、本質的にピクセルがすでに存在する場所にピクセルを追加することになります。上記のセットでは原点を背景パターンに設定しているので、背景パターンのみが実際に一致します。別の方法は、原点を常に「気にしない」要素値に設定することです。これを行うことで、同じカーネルパターンを「Thicken」に使用し、後述するように「Thinning」にも使用できます。そのため、より良いルールは、原点を「気にしない」に設定することです。
Thicken」操作を生成する別の方法は、このカーネルの「Hit-And-Miss」の結果と特別な「Unity」カーネルの結果の和集合を生成して、結果に元の画像を含めることです。

たとえば…

  magick man.gif -define morphology:compose=Lighten \
                  -morphology HitAndMiss 'Unity ; 3x1+2+0:1,0,0' hmt_thicken.gif
[IM Output] ==> [IM Output]
実際、上記の例のマルチカーネル合成設定は必要ありません。「Hit-And-Miss」メソッドは、ユーザーによって定義されていない場合、デフォルトでこの合成設定を具体的に設定するためです。


通常、「Thicken」は線などの形状を拡大するために使用されますが、線を長くするわけではありません。「ConvexHull」カーネルとして知られる特別なカーネルセットを使用すると、これを行うことができます。たとえば…

  magick -size 80x80 xc:black -fill none -stroke white \
          +antialias   -draw 'line 10,20 70,60'     man_line.gif
  magick man_line.gif   -morphology Thicken ConvexHull  thick_line.gif
[IM Output] ==> [IM Output]

Thicken - 八角形凸包

実際の「ConvexHull」カーネルは、画像形状で動作するように設計されており、形状を「八角形凸包」に拡張します。つまり、極端な値の間のすべてのギャップを埋めて、「八角形」のオブジェクトを作成しようとします。

  magick man.gif -morphology Close Diamond \
                  -morphology Thicken:-1 ConvexHull \
                  -morphology Close Diamond       man_hull_full.gif
[IM Output] ==> [IM Output]
詳細と2つの「Close」メソッドが必要な理由については、「ConvexHull」カーネルの定義を参照してください。
冗長出力設定をオンにすると、反復処理の様子を観察できます。ただし、上記の方法では非常に時間がかかることがわかります。「Thicken」の各反復処理では、形状に数ピクセルしか追加されません。そのため、完全な「ハル」が完成するまでに多くの反復処理が必要になる可能性があります。この具体的な例では、8カーネルの「ConvexHull」を使用して、画像に80回の「Thicken」反復処理が必要でした。つまり、上記には実際には640回のプリミティブな反復処理と、2つの「Close」メソッドの実行に必要なさらに4回のプリミティブな反復処理が必要でした。これはかなりの時間を要する可能性があります。基本的に、ヒットアンドミス・パターンマッチングを使用した反復処理は非常に遅く、代替手法が見つかる場合は、代わりにそれを使用する必要があります。凸状ハルと元の形状の交点(Darken合成)を求めることで、この八角形形状の作成の原因となった元の画像の点を特定することもできます。

  magick man_hull_full.gif \
              -morphology EdgeIn Diamond man_convex_edge.gif
  magick man.gif man_convex_edge.gif \
          -compose Darken -composite man_extremities.gif
[IM Output] n [IM Output] ==> [IM Output]
凸状ハル内に収まり、かつ上記凸状ハルのすべての辺に少なくとも1つのピクセルを含む任意の連結形状は、同じ八角形の凸状ハルを生成します。

グレースケール画像による太線化

グレースケール画像を処理する場合、「Thicken」は「ヒットアンドミス」の前景と背景の分離結果を元のピクセルに追加します。したがって、これは「元の」ピクセルが「背景」セットにない場合でも、一致するピクセルを明るくするために使用できます。たとえば、上記の手順から角検出の例を繰り返しますが、形状の50%グレーバージョンを使用します。

  magick man.gif   -evaluate multiply 0.5   man_grey.gif
  magick man_grey.gif  -morphology Thicken Corners  thick_corners.gif
[IM Output] ==> [IM Output]
Thicken」でImageMagickのHDRIバージョンを使用する場合は、画像のピクセル値範囲の上限を超えないように、結果を「-clamp」または「-auto-level」する方が良いでしょう。

細線化 ( )   (形状からのピクセルの減算)

Thinning」メソッドは「Thicken」の双対です。このメソッドはピクセルを追加するのではなく、元の画像からピクセルを減算します。たとえば、右端から4ピクセル内にあるピクセルをすべて削除します。

  magick man.gif   -morphology Thinning '5x1+0+0:1,1,1,1,0' thin_right.gif
[IM Output] [IM Output] ==> [IM Output]
Thinning」が正しく機能するには、パターンマッチングカーネルに前景ピクセルを含む原点が必要です。そうでなければ、形状から削除する一致するピクセルがありません。
Thinning」操作を生成する別の方法は、元の画像から「ヒットアンドミス」の結果を相対補集合MinusSrc合成を使用)することです。「Unity」カーネルを使用して、カーネルリストの先頭にその画像を含めることができます(「減算」するため)。

たとえば…

  magick man.gif -define morphology:compose=MinusSrc \
          -morphology HMT 'Unity ; 5x1+0+0:1,1,1,1,0' hmt_thinning.gif
[IM Output] ==> [IM Output]
これは、すべてのカーネルの指定されたピクセルを一度に削除する「交差」スタイルの細線化であり、「反復」スタイルとは異なり、各カーネルから順番にピクセルを削除します。詳細については、細線化スタイルを参照してください。

線の連結性

将来:4連結線と8連結線IMフォーラムの議論を参照してください。8連結線から4連結線へ

エッジ検出出力の細くする

細線化の最も一般的な用途の1つは、Sobel畳み込みなどのエッジ検出器の閾値出力を、線の全長を維持しながら、1ピクセルの厚さの線に減らすことです。距離勾配画像を使用した例

スケルトンまで細くする

Thinning」画像は、「Thicken」よりも実際には一般的に使用されています。これは、形状をスケルトンなどのより扱いやすい形式に減らすために使用されるためです。これは後で説明しますが、形状の2つ以上のエッジ間のピクセルの中心線であることを目的としています。スケルトンは、非常に複雑な形状を非常にうまく記述するため重要です。たとえば、ループの数、線分、およびそれらの配置方法を見つけるために画像を処理すると、持っている形状について多くの情報がわかります。そこで、「Thinning」を使用して人の形状のエッジを繰り返し減らし、「細線化されたスケルトン」を作成してみましょう。

  magick man.gif  -morphology Thinning:-1 Skeleton  man_raw_thinned.gif
[IM Output] ==> [IM Output]
上記に関する冗長レポートでは、18回の反復処理(8つのカーネル、合計144回のプリミティブな反復処理)が行われたことが示されます。これは、その凸状ハル(上記)を見つけるよりもはるかに高速です。細線化カーネルは、一度の反復処理でピクセルの行と列全体を削除し、一度に数個だけを削除しないためです。「Skeleton」カーネルセットは穴を拡張できなかったため、穴と外縁間の中心線が見つかりませんでした。これは、この特定のスケルトン細線化カーネルの重大な欠陥であり、カーネルが細線化の一致を行う前に少なくとも背景ピクセルを必要とすることによって発生します。この問題を解決するために、スケルトン細線化カーネルのセットを使用できます。より簡単な解決策は、カーネルに処理対象を与えるために画像を少し侵食することです。また、元の形状を青色で残すために、「赤」と「緑」のチャンネルのみを侵食して細線化します。

  magick man.gif -channel RG -morphology Erode Diamond  man_erode.gif
  magick man_erode.gif -channel RG \
          -morphology Thinning:-1 Skeleton +channel  man_skeleton.gif
[IM Output] ==> [IM Output]
画像内の穴はすべて拡大して、その周りのより大きな連続ループが生成されていることもわかります。
侵食された穴の周りのクローズアップです。

  magick man_skeleton.gif -crop 22x22+47+29 +repage \
          -scale 120x120    man_skeleton_zoom.gif
[IM Output]
穴とエッジの間に正確な中心線が生成されなかったことに注意してください。また、形状が侵食されたため、線は元の形状の端まで届かず、1ピクセル短くなります。つまり、線の端がわずかに「剪定」されています。「侵食」ソリューションの欠点です。スケルトンは八角形線に限定されているため、多くの詳細がありませんが、この場合は、その簡素化が好ましい場合があります。以下のスケルトンのセクションを参照してください。これは従来の「Skeleton」カーネルであり、ご覧のように、スケルトンのすべての部分が「4連結」または「ダイヤモンド連結」になるように、太い対角線が生成されます。「Skeleton」カーネルには他のバリエーションがあり、結果の「細線化されたスケルトン」に他のバリエーションが生成されます。より細い8連結スケルトン前述のように、この従来のスケルトンには太い対角線があります。しかし、多くの場合、これは「薄い」ほどではありません。状況によっては、わずかに薄いスケルトンが必要な場合があります。つまり、「4連結」スケルトンではなく「8連結」スケルトンが必要になります。
1つの解決策は、「Skeleton:2」カーネル(HIPR2グラフィックチュートリアルウェブサイトにあります)など、別のスケルトン生成バリアントを使用することです。例として…

  magick man.gif   -channel RG  -morphology Erode Diamond \
          -morphology Thinning:-1 Skeleton:2 +channel  man_skeleton_hipr.gif
[IM Output]
そして、ループ領域のズームを示します。結果のスケルトンは8連結で、対角線がより細くなっています。

  magick man_skeleton_hipr.gif -crop 22x22+47+29 +repage \
          -scale 120x120    man_skeleton_hipr_zoom.gif
[IM Output]
しかし、そのようなスケルトンは従来のスケルトンほど正確ではないことがわかりました。基本的に、テストケースでは、対角線が間違った側に「細線化」されていることがわかりました。基本的に、削除される対角線の側は、カーネルセット内の「角」細線化カーネルの順序によってのみ制御され、形状の性質による決定ではありません。
別の方法としては、従来の4連結スケルトンを取り、対角線の端点を基準として、対角線が常に外側に細線化されるように細線化することです。「Diagonals」細線化カーネルは、その後「Corners」カーネルを使用して「仕上げる」ために設計されています。そこで、前の従来のスケルトンをさらに細線化してみましょう。

  magick man_skeleton.gif -channel RG \
          -morphology Thinning:-1 Diagonals \
          -morphology Thinning Corners   man_thin_skeleton.gif
[IM Output] ==> [IM Output]
従来の4連結スケルトンを細線化するというこの手法は、「Skeleton:2」バリアントを直接使用する場合よりもわずかに遅くなります。追加の細線化には、8つのカーネルの8回の細線化反復処理、つまり64回のプリミティブな反復処理が必要でした。または、「Corners」カーネルのみを使用することもできますが、これにより、対角線のどちらの側が細線化されたかという「ランダム」な選択のみを含む「HIPR」バリアントが生成されます。ただし、これは4つのカーネルの1パスしかかかりません。そのため、「Diagonals」を使用する場合よりもはるかに高速です。いずれにしても、従来の4連結スケルトンから始めて、非常に簡単に8連結バージョン(ある種類)を生成できます。

スケルトン情報

スケルトン(おそらく4連結バージョンと8連結バージョンの両方)ができたら、次の手順は通常、スケルトンに関する詳細情報を調べることです。たとえば、「線の自由端」、「線分岐点」、「線ループ」がいくつ存在するかです。線分の端の数ここでは、以前に生成したスケルトン(「赤」チャンネルから抽出)で「LineEnds」のヒットアンドミス検索を使用します。次に、それらの線の端を膨張させてリングにし、色を付けてから元のスケルトンとマージして、位置を非常に目に見えるようにします。

  magick man_skeleton.gif -channel R -separate +channel \
          -morphology HMT LineEnds man_ends.gif
  magick man_ends.gif -morphology Dilate Ring -background Red -alpha Shape \
          man_skeleton.gif +swap -composite man_ends_marked.gif
[IM Output] ==> [IM Output] ==> [IM Output]
線はすべて互いに接続されているか、ピクセルのループが見つからなかったことに注意してください。自由な線の端のみが示されていました。ピクセル数(ヒストグラム出力を使用)を実行すると、このスケルトンによって12本の線の端が生成されたことがわかります。線分岐点の数画像内の線分岐点の概算数を取得するには、「LineJunctions」カーネルを8連結スケルトンで使用します。できれば、線の端の数を数えるために使用した元のスケルトンから細線化されたものを使いましょう。2つの異なるスケルトン生成バリアントを混ぜないでください。

  magick man_thin_skeleton.gif -channel R -separate +channel \
            -morphology HMT LineJunctions  man_junctions.gif
  magick man_junctions.gif -morphology Dilate Ring \
          -background Red -alpha Shape \
            man_thin_skeleton.gif +swap -composite man_junctions_marked.gif
[IM Output] ==> [IM Output] ==> [IM Output]
従来の4連結スケルトンでこのカーネルを直接使用しようとすると、「T」分岐点の一部に複数のマッチングが発生し、カウントが非常に不正確になります。ご覧のとおり、結果は12個の線分岐点であり、この特定の形状では正しくなります。ただし、一部の分岐点では、「LineJunctions」カーネルは不正確です。たとえば、4本の線の対角線「X」分岐点では1つのマッチングしか生成されませんが、直交「+」分岐点では4つのマッチングが生成されます。これらの特殊な分岐点の両方が2つのマッチングを生成する必要があります。したがって、正確なカウントを得るには、「X」分岐点ごとに1つの値を追加し、「+」分岐点ごとに2つのカウントを減算する必要があります。
ループのないスケルトンでは、分岐点の数は線の端の数より2つ少なくなります。ただし、線の端の数と分岐点の数が等しい場合、画像内に1つ以上の連続するピクセルループが存在することを意味します。このスケルトンには、12個の線の端と12個の分岐点があります。そのため、画像のどこかに少なくとも1つの連続するピクセルループが含まれています。ループの数将来:連結オブジェクトラベリング

線の剪定

この画像には少なくとも1つのループがあることがわかっています。形状をこれらのループのみに単純化したいとしましょう。解決策は、すべての線端を繰り返し「プルーニング」して、すべて削除するまで続けることです。このような4連結スケルトンでは、「線端」カーネルのより小さなセットを使用することで、処理速度を約2倍にすることができます。

  magick man_skeleton.gif -channel G \
          -morphology Thinning:-1 'LineEnds:1>' man_loop.gif
[IM Output] ==> [IM Output]
これに関する詳細なレポートでは、4つのカーネルで75回の反復を行い、画像から自由端を持つすべての線を「プルーニング」するために300回のプリミティブな統合が行われたことが示されました。つまり、スケルトンを見つけるために使用された操作の約2倍であり、この操作がどれほど集中的になる可能性があるかを示しています。「線端」カーネルの完全なセット(8個のカーネル)を使用した場合も、75回の反復が必要になりますが、カーネルが2倍になるため、600回のプリミティブな反復になります。

線の高速剪定

Fast Complete pruning technique..

  1/  Find line ends, and line junctions.
  2/  Delete the line junctions to completely disconnect all line segments.
  3/  Flood fill, or use contitional dilate to remove 'line end' segments.
  4/  Restore line junctions.
  5/  use that as a map on original image to restore 'loops'.

最初のステップについては既に説明しました…その結果…

  magick man_skeleton.gif -channel R -separate +channel \
          -morphology HMT LineEnds man_ends.gif
[IM Output]
すべての線分を切断(または分離)するには、「線分接続部」カーネルを使用できます。ただし、デフォルトのカーネルセットでは、「T」字路を完全に切断できません(単にそれらの位置を特定するだけです)。
すべての線分を適切に切断するには、カーネルセットに直交する「T」字路カーネルを追加する必要があり、「+」字路も追加することをお勧めします。例:

  magick man_skeleton.gif -channel R -separate +channel \
      -morphology HMT 'LineJunctions;LineJunctions:3>;LineJunctions:5' \
      man_disconnect.gif
[IM Output]
これらのマッチングによる間引きは実際にはセグメントを切断しますが、これはすべて1ステップで行う必要があります(間引きスタイルを参照)、そうでなければ正しく機能しません。

  magick man_skeleton.gif -channel R -separate +channel \
      -define morphology:compose=Darken \
      -morphology Thinning 'LineJunctions;LineJunctions:3>;LineJunctions:5' \
      man_line_segments.gif
[IM Output]
切断されたセグメントを示す「ループ」のズーム画像を次に示します。

  magick man_line_segments.gif -crop 22x22+47+29 +repage \
          -scale 120x120    man_line_segments_zoom.gif
[IM Output]
この時点で、以前に検出された「線端」と一致する線分を削除できます。これは、それらの「シード」ポイントから「フラッドフィル」を実行して削除することで行うことができます。ただし、これは4連結スケルトンでのみ機能し、フラッドフィルが想定しているものです。ここに例あるいは、条件付き膨張を使用してすべての点を同時に見つけて削除することもできます。ここに例 - 条件付き膨張または侵食が利用可能な場合。ここで線分接続部を復元し、1回プルーニングを実行し、残っている単一ピクセルを削除すると、すべての線分を迅速に削除できます。これは多くのステップのように見えますが、同じ結果を得るために「線の端をプルーニングする」操作を300回実行するよりもはるかに高速です。

間引きスタイル - 順次または同時

線分の端を1回だけ「プルーニング」し、元の画像と比較すると、線の正確な形状と向きに応じて、線分が2〜4回プルーニングされていることがほとんどです。たとえば(結果の画像を拡大)は、デフォルトの線端間引きです。

  magick -size 10x10 xc:black -fill white \
          +antialias  -draw 'line 1,7 8,3' line.gif
  magick line.gif -channel GB \
          -morphology Thinning LineEnds  line_seqential.gif
[IM Output] ==> [IM Output]
つまり、デフォルトでは、各「間引き」カーネルは、前のカーネルの結果に対して順次適用されます。つまり、1つのカーネルによって選択されたすべてのピクセルを削除してから、その結果に次のカーネルを適用します。これにより、(実際にはそうしますが)線の同じ端からさらに多くのピクセルが選択される可能性があります。言い換えれば、デフォルトでは、提供されたすべてのカーネルを通した1回の完全な「反復」に対して、線の端を複数回間引きます。つまり、この演算子の単一の反復によって削除されたピクセル数を数えることで、すべての線の長さを正確に把握することはできません。詳細出力を信頼することはできません。ただし、「間引き」の動作を変更して、すべてのカーネルを通した単一の「ヒットアンドミス」反復によって検出されるピクセルセットのみを削除するように変更できます。言い換えれば、すべてのカーネルを最初の反復の同じ画像に適用し、それらをマージしてから、それらのピクセルを一度だけ削除します。つまり、すべてのカーネルに対して選択されたHMTピクセルを同時に削除します。基本的に、マルチカーネル合成設定を「Darken」合成方法を使用するように設定すると、まさにそれが行われます。具体的には、選択されたピクセルの単一の削除に対して、すべての選択されたピクセルをマージします。例…

  magick line.gif -channel GB -define morphology:compose=darken \
          -morphology Thinning LineEnds  line_simultaneous.gif
[IM Output]
ここで起こったことは、「パターンマッチングカーネル」の各カーネルが元の画像にのみ適用されることです。元の画像に一致したピクセルは、すべて一緒に収集されます。「darken」合成を使用することで、元の画像に対するすべてのカーネルの結果の「交差」のみを削除します。しかし、削除は、すべてのカーネルを通した1回の反復に対して、すべて1ステップで行われます。その結果、複数のカーネルがその線端と一致する可能性があっても、線端は一度しか一致しなくなります。したがって、異なるカーネルによって2個以上のピクセルではなく、端の単一ピクセルのみが削除されます。要約すると、「Darkenマルチカーネル合成設定を追加すると、「間引き」方法は「同時間引き」(すべてのカーネルが同時に)ではなく「順次間引き」(一度に1つのカーネル - デフォルト)を実行するようになります。
ただし、これにより線端のプルーニングがより適切に動作するようになりますが、速度が低下し、間引きの全体的な結果が変わる可能性があります。左右の両端を同時に間引くことで「間引き」されたボックスの場合を考えてみましょう。

  magick -size 10x10 xc:black -fill white -draw 'rectangle 4,1 5,7' rect.gif
  magick rect.gif -channel GB -define morphology:compose=darken \
          -morphology Thinning Edges  rect_simultaneous.gif
[IM Output] ==> [IM Output]
「同時間引き」によって、中心の矩形が完全に削除されました!何が起こっているかというと、形状が2ピクセルの厚さに間引かれ、その後、「厚い」中心矩形の両側がパターンに一致し、両側が「間引か」れました。スケルトンの間引きを行う場合も同じことが起こります。一方、デフォルトの「順次間引き」では…

  magick rect.gif -channel GB \
          -morphology Thinning Edges rect_seqential.gif
[IM Output]
ご覧のとおり、ピクセル(右側)の1つがスケルトンの中心線として保持されました。つまり、カーネルの1つのセットが最初に「厚い」中心線の片側を間引きしましたが、後のカーネルはこの「薄い」線と一致しなかったため、削除されませんでした。基本的に、「順次間引き」(デフォルト)の方が特別な「同時間引き」よりも優れている状況があり、その逆もあります。

パターンマッチングカーネル

前述のように、「パターンマッチング」または「ヒットアンドミス」カーネルには、前景、背景、「気にしない」の3種類の要素を含めることができます。「1.0」または(白)は前景ピクセルに一致します。「0.0」または(黒)は背景ピクセルに一致します。「0.5」または特殊値の「Nan」または「-」を使用して、近傍に属さないピクセル要素を表すことができます。したがって、「気にしない」要素となります。「ヒットアンドミス」は、最小の前景ピクセルが最大の後景ピクセルよりも大きい場所のみに一致します。その後、これらの2つの値の差、または0を返します。 [IM Output]

ピーク

ピーク」カーネルは、以前に示した「リング」カーネルの拡張です。2つの半径引数により、中心の「原点」にある単一の前景ピクセルを取り囲む背景ピクセルの「リング」が生成されます。より便利な「ピーク」カーネルの例をいくつか示します…
[IM Output] [IM Output] [IM Output] [IM Output] [IM Output] [IM Output]
上記のカーネルを使用して、暗いピクセルの海の中で単一ピクセルの「ピーク」値を明確に特定したり、より大きなリングの中に完全に収まる小さな形状を見つけることができます。相関パターンマッチ検索のコントラストを向上させるのに特に役立ちます。

エッジ


エッジ」カーネルセットは、形状の平らなエッジ上のピクセルに一致します。90度の鋭角には一致しませんが、八角形の形のコーナーピクセルには一致します。
[IM Output]
ご覧のとおり、90度の回転はすべて生成されますが、「フリップフロップ」ミラー順序で並べ替えられ、一般的により良い結果が得られます。通常、このカーネルは一種の画像「間引き」カーネルとして使用されますが、現状では、対角線を間引いたり、画像の適切なスケルトンを生成したりすることはできません。例…

  magick man.gif -channel RG \
          -morphology Thinning:-1 Edges   thin_edges.gif
[IM Output] ==> [IM Output]
以下の「スケルトン」カーネルを参照してください。

コーナー

コーナー」カーネルは、画像のエッジ周辺の対角線のコーナーピクセルを見つけます。使用方法の例については、上記「ヒットアンドミス」を参照してください。
[IM Output]
たとえば、ここでは、すべての対角線を間引こうとして使用しました…

  magick man.gif -channel RG \
          -morphology Thinning:-1 Corners  thin_corners.gif
エッジ」カーネルと組み合わせて、スケルトン間引きの1つの方法を作成できます。この例については、以下の「スケルトン」カーネルを参照してください。
[IM Output]

対角線

対角線」カーネルは、単純に「コーナー」カーネルを使用して4連結対角線を8連結対角線に間引くための代替手段です。これを使用して、コーナーから中心に向かって外側のピクセルセットを削除することで、4連結線を間引くことができます。
[IM Output]
結果は、「コーナー」カーネルを使用して、90度のコーナーを見つけて間引くことで完了する必要があります。使用方法の例については、より薄いスケルトンを参照してください。 **対角線のサブタイプ** カーネルに「タイプ[,角度]」引数を指定することで、上記のカーネルセットを作成するために使用された特定のサブタイプを選択できます。
[IM Output] [IM Output]
これにより、対角線を正確に間引きする方法で、独自の特定のカーネルセットを指定できます。たとえば、上記の両方のカーネルを同じ角度値で使用して、4種類の対角線のそれぞれを個別に間引くことができます。これにより、特定の対角線のそれぞれを一度に1つずつ繰り返し削減し、それらの特定の対角線がすべて間引かれた時点で中止し、実行される「プリミティブな形態学ステップ」の総数を減らすことができます。例が必要指定されているとおり、デフォルトのカーネルセットは、すべての対角線を同時に繰り返し間引くことを試みます。つまり、すべての対角線が間引かれるまで、すべてのカーネルが適用されます。つまり、多くの「プリミティブな形態学ステップ」が不要になり、各ループ中にほとんどのカーネルが画像に何も変更を加えません。完全な例が必要 4つの対角線のそれぞれは、特定の角度の対角線が「アーク」の一部である場合など、両端が一緒に間引かれるように、両方のカーネルペア(特定の角度ごとに)を使用して実行する必要があることを忘れないでください。このタイプの間引き/増厚操作に関する関連する議論は、IMフォーラムにあります。8連結線から4連結線へ

線端

上記線の端部の間引きに示されているように、「LineEnds」カーネルセットは、線の端点を検出するために設計されています。より具体的には、鋭い点の端点を検出します。
[IM Output]
ご覧のとおり、これは少なくとも2ピクセルを持つ線のみを検出し、一致するピクセルは背景ピクセルで「キャップされている」または「囲まれている」必要があります。たとえば、ここでは「ヒットアンドミス」を使用して、すべての線の端点を検出します。

  magick lines.gif -morphology HMT LineEnds  hmt_lineends.gif
[IM Output] ==> [IM Output] ==> [IM Output]
この画像には多くの線の端点がありますが、何らかの「ループ」で終わる線は一致しません。このカーネルを使用して「間引き」処理を行う場合、「反復間引き」スタイル(デフォルト)を使用すると、連続するカーネルが線の同じ端点を2回以上一致させる可能性があり、そのため「間引き」方法の単一反復中に線が何度も縮小される可能性があります。詳細は間引き - シーケンシャル vs. 同時を参照してください。 線の端点のサブタイプこのカーネルは、「type[,angle]」引数を与えることで、上記の「LineEnds」カーネルセットの生成に使用された単一カーネル定義のいずれかを返すこともできます。
[IM Output] [IM Output] [IM Output] [IM Output]
これらは、必要に応じて回転カーネルリストに展開したり、必要に応じて特定の「angle」に回転したりできます。デフォルトの「LineEnds」セットは、実際にはカーネル定義を使用しています。
LineEnds:1> ; LineEnds:2>
LineEnds:3」は、対角線上の「LineEnds:2」の直交等価物であり、対角線のコーナーやジャンクションから離れた線の端点のみを検出します。 「LineEnds:4」は従来の線の端点カーネルであり、循環的に回転させて8つのカーネルを生成します(例:「LineEnds:4@」)。ただし、直交する「T」ジャンクションに接続する線の最後のピクセルを検出できません。ただし、上記で定義されているデフォルトの「LineEnds」セットは、同じ数のカーネルを使用して「T」ジャンクションの最後のピクセルを検出します。

LineJunctions

LineEnds」が線群の端点を検出するのに対し、「LineJunctions」は3本以上の線が交わる点を検出します。
[IM Output]
たとえば、ここでは「ヒットアンドミス」を使用して、すべての線のジャンクションを検出します。

  magick lines.gif -morphology HMT LineJunctions hmt_junctions.gif
[IM Output] ==> [IM Output] ==> [IM Output]
LineJunctions」カーネルは一般的に2つの目的で使用されます。
  • 画像内の線のジャンクションの数をカウントし、それによってスケルトンの線分の数を求めます。
  • すべての線分を互いに接続解除します。
ただし、上記の画像の「T」と「+」ジャンクションでは、「Y」ジャンクションカーネルは、実際の交点から1ピクセル離れた点を一致させます。このため、ジャンクションカウントは、特に「+」ジャンクションではジャンクションカウントに必要な2つではなく4つのマッチが見つかるため、期待どおりにならない可能性があります。注意が必要です。詳細はスケルトン情報高速ライン間引きを参照してください。カーネルは実際には前景ピクセルのみを定義するため、「ヒットアンドミス」メソッドではなく、「浸食」メソッドとして単純に適用できます。 線のジャンクションのサブタイプこのカーネルは、「type[,angle]」引数を指定することで、さまざまなサブタイプにもアクセスできます。これを使用して、特定の種類の線のジャンクションを検索できます。
[IM Output] [IM Output] [IM Output] [IM Output] [IM Output]
カーネル「LineJunctions:2」は「LineJunctions:3,45」でも指定でき、同様に「LineJunctions:5」と「LineJunctions:4,45」は同等です。デフォルトの「LineJunctions」カーネルセットは、最初の2つのジャンクション定義(「Y」と対角線上の「T」ジャンクション)のみを以下の方法で使用します…
LineJunctions:1@ ; LineJunctions:2>
これは、8連結線のジャンクションに適しています。IMフォーラム「LineJunctionsで使用されるカーネル」で説明されているように、4連結線のジャンクションのみをテストする場合は、直交する「T」ジャンクションと「+」ジャンクションを探す必要があります。
LineJunctions:3> ; LineJunctions:5
ただし、「T」カーネルは「+」にもヒットするため、上記を以下に短縮できます…
LineJunctions:3>
4方向の「+」ジャンクションのみを対象とした別の画像テストを使用して、線分のカウントを決定する必要がある場合に、3方向の「T」ジャンクションから分離できます。

Ridges

Ridges」カーネルは、距離勾配画像など、ピクセルの尾根や細い線を検出するために使用されます。これらのカーネルは実験的なものであり、変更される可能性があります。デフォルトは、1ピクセルの厚さの尾根線を検出するように設計されています。
[IM Output]
Ridges:22ピクセルの厚さの尾根線を検出するように設計された、特別な拡張サブタイプです。複雑さは、この種の斜めの線を検出し、マークする必要があること、およびそれらの線のミラーを含む必要があることから生じます。
[IM Output]
このカーネルセットは、「形態学的スケルトン」が実際には1ピクセルと2ピクセルの厚さの線の両方で構成されているため重要です。

ConvexHull

ConvexHull」カーネルセットは、形状を太くして、形状の「八角形凸包」を生成するように設計されています。つまり、形状全体を含むことができる最小の八角形です。
[IM Output]
90度回転したカーネルのセットが2つあり、1つはもう1つの鏡像です。原点は実際には「背景」要素であるため、実際には「太らせる」パターンカーネルとしてのみ使用することを意図しています。ただし、このカーネルは、「man」形状にあるような水平または垂直な「スロット」を含む画像では機能しません。

  magick man.gif -channel R \
          -morphology Thicken:-1 ConvexHull  man_hull.gif
[IM Output] ==> [IM Output]
解決策は、「ConvexHull」を使用する前にこれらのスロット(および中心の穴)を「閉じる」ことです。

  magick man.gif -morphology Close Diamond \
                  -morphology Thicken:-1 ConvexHull \
                  -morphology Close Diamond       man_hull_full.gif
[IM Output]
上記では、「ConvexHull」を使用した後にも「閉じる」を繰り返しました。理由は、画像内の大きな「穴」も「太らせる」によって単一ピクセルまたは直交する「スロット」に削減されるためです。「閉じる」を繰り返すと、最終的な形状に影響を与えることなく、これらの穴が削除されます。
ここでは、元の形状(白)を凸包太らせ(赤)を使用して拡張した別の例を示します。

  magick circles.gif -channel R \
          -morphology Thicken:-1 ConvexHull  circles_hull.gif
[IM Output]
ご覧のとおり、結果は八角形であり、中心の穴は2ピクセルのスロットに削減され、閉じる準備ができています。

Skeleton

特定の形状の間引きによる「スケルトン」の生成は容易ではありません。同じカーネルセットを使用しても、カーネルの順序を変更することで、最終的な「スケルトン」のバリエーションが生成される可能性があります。このため、「Skeleton」カーネルセットを1つだけ実装するのではなく、多くのカーネルセットを実装し、「type」引数番号を指定して選択できるようにしました。

Skeleton:1

最初でデフォルトのセットである「Skeleton:1」は、最初に使用された従来の間引きカーネルです。これは基本的に上記にある「Edges」カーネルとまったく同じですが、45度刻みで循環的に回転されています。
[IM Output]

  magick man.gif -channel RG \
          -morphology Thinning:-1 Skeleton   thin_skeleton1.gif
[IM Output]
その結果、形状の妥当な「間引きされたスケルトン」が生成されますが、対角線は片側が少し厚い傾向があります。基本的に生成されるスケルトンは4連結であり、高速間引き手法を使用できます。また、このカーネルセットは、画像内の単一ピクセルの穴を正しく拡張しません。言い換えれば、その穴の周りのスケルトンは、穴と画像の残りの部分の間の中心線には近づきません。詳細はスケルトンへの間引きを参照してください。

Skeleton:2

Skeleton:2」バリアントは、従来の「Skeleton:1」バージョンとほぼまったく同じです。HIPR2画像処理リソースドキュメントで見つかりました。
[IM Output]

  magick man.gif -channel RG \
          -morphology Thinning:-1 Skeleton:2   thin_skeleton2.gif
[IM Output]
これを前のセットと比較すると、コーナーの内側のピクセルが削除されていることがわかります。これにより、間引き操作で対角線から余分な厚さを削除できます。ただし、この対角線の間引きは対称ではなく、画像の形状とカーネルが適用される順序に大きく依存します。Skeleton:2」バリアントは、「Edges;Corners」カーネルリストを組み合わせたものと非常に密接に関連しています。
[IM Output]

  magick man.gif -channel RG \
          -morphology Thinning:-1 'Edges;Corners' thin_edge-corner.gif
[IM Output]
これと「Skeleton:2」で使用されているものとの唯一の違いは、リスト内のカーネルの順序です。同じカーネルセットが使用されているにもかかわらず、結果として得られるスケルトンがどのように異なるかに注目してください。これは、間引きによるスケルトンの生成は実際には非常に脆弱であり、単純な順序の変更でも接続されたスケルトンに異なる結果をもたらす可能性があることを示しています。

Skeleton:3

Skeleton:3」は、間引きカーネルの使用に関する正式な研究(下記のThinSEカーネルを参照)において、Dan S. Bloombergによる1991年の研究論文「Connectivity-Preserving Morphological Image Transformations」で開発されました。彼はそのようなスケルトンのかなりの数を開発し、研究の結果を表にまとめました。以下は、4連結スケルトンを生成できる、彼が考え出した最良のものです。ただし、以前のスケルトンとは異なり、3つの回転カーネル(合計12個)を使用する必要があります。
[IM Output]

  magick man.gif -channel RG \
          -morphology Thinning:-1 Skeleton:3   thin_skeleton3.gif
[IM Output]
回転カーネルの最初のグループには、単一の背景ピクセルのみが含まれていることに注意してください。つまり、このスケルトンは「man」形状にある単一ピクセルの穴を開き、中心線に沿ったスケルトンを生成できました。あまり多くの分岐を生成せず、クリーンで滑らかな線を生成し、完全に間引きもします。全体として、これはより優れたスケルトン間引きカーネルの1つです。

ThinSE

Dan S. Bloombergによる研究論文 "Connectivity-Preserving Morphological Image Transformations" は、4連結線または8連結線を保持するように設計された、最小限の3x3の「Thinning Structure Elements」の完全な範囲を、第一原理から実際に開発しました。'ThinSE:{type}' カーネルセットは、これらの構造要素のリストであり、接続性と保持力に基づいてグループ分けされて以下に示されています。'{type}' は、研究論文で使用されている上付き文字(連結性)と下付き文字の要素番号に基づいた数値です。そのため、カーネル 'ThinSE:41' は、4連結線の保持要素の最初のものです。回転角度を追加したり、指定されたカーネル定義に回転または鏡像回転フラグのセットを生成することもできます。
[IM Output] [IM Output]
[IM Output] [IM Output]
[IM Output] [IM Output]
最後の「General Thinning Kernel」、'ThinSE:482' は、エッジ検出カーネルのセットを定義するために使用されるカーネルと同じであることがわかるでしょう。この一般的なカーネルは、上記に示されている他のすべてのシンニングカーネルが開発されたコアカーネルです。これはセットのデフォルトカーネルです。一般的なカーネル 'ThinSE:481' と 'ThinSE:482' は、回転的に関連付けられている唯一のカーネルであることに注意してください。つまり、'ThinSE:481x45' は 'ThinSE:482' と同等です。他の多くの組み込みHMTカーネルセットは、実際にはこれらのカーネルで内部的に定義されています。たとえば、カーネルセット 'ThinSE:41 ; ThinSE:42 ; ThinSE:43' とその回転拡張は、'Skeleton:3' セットを作成するために使用される12個のカーネルを生成します。このスケルトンは、良好な細線化されたスケルトンを生成するために発見された最良のカーネルセットとして論文に記載されていました。他のスケルトン生成シンニングカーネルも、上記のカーネルを使用して定義されています。
ただし、'ThinSE:44'などの一部のカーネルは、「連結性」を保持するように設計されていますが、実際には行の端を保持しておらず、そのため、スケルトンが単一点または接続されたリングのセットに刈り込まれる原因となります。すべてのカーネルが中心の原点値を定義するわけではなく、これはこれらの「シンニングカーネル」がシェイプの細線化だけでなく、シェイプの太線化にも使用でき、SKIZ(影響範囲)を生成できることを意味します。注意深く見ると、4連結カーネルのそれぞれが、8連結セットに負の値と180度回転した形で存在し、その逆もまた同様であることに気づくでしょう。たとえば、'ThinSE:41' と 'ThinSE:84' は互いの負の回転です。その理由は、4連結と8連結が、シンニングと太線化の形態学的メソッド(負の画像を使用)の双対性によって互いに密接に関連しているためです。本質的に、4連結を保持する「シンニングカーネル」を使用して画像を太線化すると、シェイプの周りに8連結の背景スケルトン(刈り込まれていないSKIZ)が生成され、その逆も同様です。したがって、負の形式を使用することで(シンニングと太線化のメソッドが交換されるため)、同じ操作に対して別の形式の連結性を生成できます。

距離勾配形態学

'Distance' 形態学メソッドは、可能な多くの特殊化されたメソッドの最初のものです。これは、シェイプの「エッジ」から各前景ピクセルの距離を測定するために特殊なカーネルを使用します。より具体的には、「ゼロ」または「黒」のカラー値からのピクセルの距離を測定します。ただし、純粋なバイナリ(白黒)のシェイプでのみ機能しますが、後述するように、アンチエイリアシングされたシェイプを修正して距離メソッドで使用できます。そして、特別に設計された距離カーネルでのみ機能します。距離カーネルは画像に適用され、各ピクセルに最小ピクセル値と、その距離に対するカーネル値が割り当てられます。これは、前の形態学的メソッドで見たように、複数の反復を必要としないアルゴリズムを使用して、画像全体に同時に適用されます。このため、単一のプリミティブ形態学的演算とほぼ同じ速度であり、細線化スケルトン形態学的メソッドなどに比べて非常に高速です。これは画像全体に適用されるため、「iteration」引数は必要ありません。同じカーネル操作を繰り返しても(反復しても)、結果にはそれ以上の変更は生じません。
IM v6.6.9-4より前では、カーネルが通常のErosionと同様の技術を使用して適用されたため、「-1」の反復回数が要件でした。これは不要になり、ゼロ(操作なし)以外の反復引数は無視されます。
これは、「Distance」メソッドを「man」シェイプで使用した例です。

  magick man.gif -threshold 50% \
          -morphology Distance Euclidean:4 \
          +depth  distance.png
[IM Output] ==> [IM Output]
非常にエキサイティングでしたね。いいえ!問題は、最終画像の色が非常に暗すぎることです。ただし、高性能モニターを使用していて、注意深く見ると、「man」があった場所に非常に暗い「ゴースト」のようなシェイプが見えるかもしれません。少なくともこの小さな画像では、すべてのピクセルがエッジに「近い」ため、非常に大きな「距離」値が得られないことが原因です。
'Distance' メソッドを使用する場合は、PNG画像が推奨されます。つまり、JPEGのようなカラーロスなしで、GIFなどよりも高い出力値「深度」を提供できるためです。

また、8ビットGIFソース画像を読み込んだ場合でも、出力が16ビット深度(IMのQ16バージョン用)にリセットされるように、「+depth」という深度設定を使用した理由でもあります。

IMのQ8バージョンを使用しているユーザーは、距離カーネル(下記)で「scale」距離カーネルオプションについて確認し、使用される「スケーリング値」を調整することをお勧めします。(次のセクションを参照)IMのQ8バージョンと非整数距離カーネル(このユークリッド距離カーネルなど)の組み合わせは推奨されませんが、精度が低い結果が生成されます。

これらの2つの側面をよりよく理解するには、品質と深度に関するIM例セクションを参照してください。

デフォルトでは、組み込みの距離カーネルは、「100 × {pixel_distance}」のカラー値を各ピクセルに適用します。ピクセルがこの値よりも明るい場合は、その値に設定されるため、ピクセルからエッジまでの最小距離が割り当てられます。その結果、シェイプのエッジに沿ったピクセルには、背景色よりも100単位の値が割り当てられます。さらに内側の次のピクセルには、さらに100単位が割り当てられます。正確にどのくらいの単位が割り当てられるかは、使用される距離カーネルによって異なります。したがって、上記の画像で設定された最大のカラー値を見てみましょう。

  magick identify -verbose distance.png | grep max:
[IM Text]
つまり、結果の画像で最大のカラー値は '1616' であり、画像で最も明るいピクセルは非常に暗い2.5%のグレーで、エッジからの距離は16.16ピクセルです。言い換えれば、非常に暗い、しかし完全に黒ではない画像が見えます。
数学的な "-auto-level" を使用して結果のカラー値を調整し、エッジから最も遠くにある、つまり最も明るいピクセルを白に設定しましょう。このようにして、「距離勾配」の効果を実際に確認できます。

  magick distance.png -auto-level  distance_man.gif
この画像では生成された正確な「距離」値ではなく、距離の目に見える効果のみを気にするため、画像をGIF画像ファイル形式で保存して表示できるようになりました。
[IM Output]
これが「Distance」メソッドの機能です。使用される特定の距離カーネルに従って、各ピクセルがエッジからどの程度離れているかを定義する、指定されたシェイプ全体に勾配を生成します。
結果の「距離」画像を明るくする別の方法は、実際にはより大きな距離カーネルの「scale」値を使用することです。たとえば、3000単位の値(Q8ユーザーはおそらく20の値を使用できます)。

  magick man.gif -threshold 50% +depth \
          -morphology Distance Euclidean:4,3000     distance_scaled.gif
[IM Output]
距離勾配が黒から白に覆われておらず、あるグレースケール値でピークに達したことに注意してください。ピークの「距離」がわかっているので、最大ピークを16.16 * 3000 => 48480、つまり約74%のグレーと計算できます。パーセンテージのスケーリング係数を使用することもできます。たとえば、エッジからのピクセル距離ごとに8%のカラー範囲値を使用します。

  magick man.gif -threshold 50% +depth \
          -morphology Distance Euclidean:4,8%    distance_scale_percent.gif
[IM Output]
ご覧のとおり、今回は最大距離に達する前に最大値の制限に達しました。距離勾配がカバーできる最大距離は(100% at maximum range) / (8% per pixel) => 12.5 pixel_distanceと計算できます。もちろん、HDRIバージョンのImageMagickを使用している場合は、少なくともClampするまで、または非浮動小数点画像ファイル形式に保存するまで、完全な距離値がメモリに保持されます。特殊な距離スケーリングフラグ '!' を使用して、関心のある最大ピクセル距離を直接指定することもできます。
シェイプのエッジからの最大距離が16.16であることがわかっているので、少なくとも18ピクセルの制限を要求します。

  magick man.gif -threshold 50% +depth \
          -morphology Distance Euclidean:4,'18!'   distance_range.gif
[IM Output]
'!' フラグは、カラー範囲の制限に達する前に「n」個のグレースケール値を与えるように距離をスケールします。そのため、1の値は、画像のエッジに直接隣接するピクセルのみを「フェザー」(またはグレーにする)だけです。ご覧のとおり、すべてのスケーリングメソッドは、「Distance」メソッドを実行しているシェイプの実際のサイズに大きく依存します。小さすぎると非常に暗くなり、ニーズに合わない場合があります。大きすぎると、ImageMagickのコンパイル時の品質の可能な最大カラー値によって距離が「クリップ」される可能性があります。カーネルの「scale」係数の詳細については、以下の距離カーネルセクションを参照してください。これらの例で使用されているmanのような「シェイプ」について、最後に1点注意しておきたいと思います。このシェイプには単一ピクセルの「穴」が含まれており、その周りに一種の「勾配井戸」が作成されました。これにより、結果の「距離勾配」画像の上半分に非常に強い影響を与えます。この解決策の1つは、「Close」を使用してその穴を除去し、シェイプを「きれいで滑らかに」することです。たとえば…

  magick man.gif -morphology Close Diamond  man_clean.gif
  magick man_clean.gif   -morphology Distance Euclidean \
                                    -auto-level   distance_clean.gif
[IM Output] ==> [IM Output] ==> [IM Output]
もちろん、これによりシェイプの「脚」の間の隙間も「閉じられる」という効果があり、最終結果の下半分に影響を与えます。代替ソリューションとしては、Floodfillメソッドを使用して画像の外側を抽出し、それを新しいマスクに変換する方法があります。その結果、穴は閉じられますが、画像の外側の境界は保持されます。たとえば…

  magick man.gif -gamma 0,1,1 -bordercolor black -border 1x1 \
          -fill red -floodfill +0+0 black -shave 1x1 \
          -channel R -separate +channel -negate  man_floodfill.gif
  magick man_floodfill.gif    -morphology Distance Euclidean \
                                    -auto-level   distance_floodfill.gif
[IM Output] ==> [IM Output] ==> [IM Output]

距離カーネル

指定されたカーネルは非常に特殊で、各ピクセルに割り当てる実際の距離測定値を定義するために使用されます。たとえば、ここでは組み込みの「距離カーネル」の1つのカーネル表示出力です。

  magick xc: -define morphology:showkernel=1 -precision 3 \
          -morphology Distance:0 Chebyshev:3     null:
[IM Text]
重要なのは、「原点」(この場合はカーネルの正確な中心)の値がゼロであるということです。これは非常に重要です。その「原点」は、より大きな値で囲まれており、その「原点」からの距離が大きくなるにつれて線形に増加します。カーネルがこの特定の方法で定義されていない場合、予期せぬ奇妙な効果が生じる可能性があります。カーネルに与えられた値は、既に「既知の」距離に追加される実際の「値」であり、その値が既に割り当てられている値よりも小さい場合、ピクセルに割り当てられます。その結果、「白」のピクセルは、エッジに近いほど暗くなり、エッジから離れるほど線形に明るくなります(既に割り当てられている値に追加されます)。提供されている組み込みの距離カーネルはすべて、2つのオプションのk_arguments…を受け入れることができます。

     {distance_kernel}[:{radius}[,{scale}[%][!]]]
最初の引数は、すべての形状カーネルと同様に、生成されるカーネルの大きさを定義するカーネルの半径です。デフォルトでは、組み込みの距離カーネルの半径は「1」に設定されており、ほとんどの場合うまく機能する非常に小さな3×3のカーネルになります。2番目の引数「scale」は、1ピクセルの長さの距離を表すために使用される距離スケールを設定します。上記の例に示されているように、デフォルト値は「100」です。つまり、最終的なピクセルまたはグレースケールの値が「300」であるピクセルは、エッジから正確に「3ピクセル」離れている必要があります。 距離スケーリング前述のように、より「正確な」距離測定のために「分数」距離を使用できるように、大きな「scale」値が使用されます。ただし、提供されている「ユークリッド」距離カーネルのみがそのような「分数」値を使用します。前の例では、割り当てられた「最大距離」値は「1700」でしたが、これはImageMagickのQ8バージョンでオーバーフローします(メモリ内のビット深度、画質を参照)。IM Q8では、カラー値は最大255(2Q => 28 => 256色の値、0から255の範囲)までの値にしか到達できません。そのため、「10」や「20」などの小さいscaleを使用すると、IM Q8コンパイル時バリアントを使用しているユーザーにとってより効果的です。「ユークリッド」カーネルで使用する場合、精度がはるかに低くなります。このため、IMのQ8バージョンを使用しているユーザーは、スケール係数を「1」にして他の「整数」距離カーネルを使用することをお勧めします。 スケール係数に「%」を含めることで、フルカラー範囲のパーセンテージとして距離スケーリングを指定することもできます。つまり、カラー値範囲の「12.5%」のスケールを使用すると、距離が使用しているIMのバージョンのカラー範囲の制限を超える前に、約8ピクセルの距離メトリックを取得できます。または、代わりに「!」を使用することもできます。これは、スケールがカラー範囲の除数であることを意味します。つまり、「20!」のスケールを指定すると、距離スケーリングは、画像のエッジから20ピクセルの位置でカラー範囲の制限に達するように設定されます。ただし、これらの「特別なスケーリングフラグ」を使用しても、IMのQ8バージョンでは範囲精度の制限が依然として深刻です。多くの距離演算に必要なデータ値の範囲がありません。もちろん、HDRIバージョンのIMでは、結果のカラー値も浮動小数点値として格納されるため、任意のscale(浮動小数点を含む)を正確に使用できます。そのような画像を浮動小数点以外の画像ファイル形式に保存しようとするときは、カラー範囲を適切に再スケールすることを忘れないでください。
ピクセルのエッジからの距離を指定するための異なる「距離メトリック」をもたらし、基本的に「最も近いエッジ」とは何かを定義する、いくつかの異なる距離測定カーネルが提供されています。

チェビシェフ(チェス盤)距離カーネル

Chebyshev」距離カーネルは最も単純で、「原点」の周りのすべてのピクセルは、その隣接ピクセルから単純に1距離単位であることを指定します。つまり、すべての8つの隣接ピクセルは互いに「隣接」しています。そのため、直近の4つの隣接ピクセルのみが1単位の距離になりますが、対角線の隣接ピクセルも正確に1単位離れています。これは、チェス盤上で「キング」または「クイーン」のチェスピースが移動するマス目の距離に似ていることが多く、そのため「チェス盤」距離メトリックとも呼ばれます。ただし、距離カーネルは、距離1ピクセルあたり100距離単位のデフォルトの{scale}係数を使用することに注意してください。そのため、原点から離れるたびに距離は100単位になります。これは、上記の前の例で使用されたカーネルでもあります。これが、実際に生成されるカーネルです…

  magick xc: -define morphology:showkernel=1  -precision 4 \
          -morphology Distance:0 Chebyshev       null:
[IM Text]
このカーネルの名前は、この形式の距離測定を最初に数学的に記述したロシアの数学者パフヌティ・チェビシェフにちなんで名付けられています。この尺度については、Wikipedia、チェビシェフ距離で詳しく知ることができます。「Chebyshev」距離測定を使用すると、ピクセルの最終距離は、最も近いエッジまでの最大のX値またはY値になります。ただし、対角線の距離は1単位しかないため、画像内の最大距離は通常、予想よりも小さくなります。このカーネル「メトリック」を使用して、「距離勾配」を生成してみましょう。ただし、何が起こっているのかを確認するために、無限の反復回数を使用する、より遅い「Iterative Distance」形態学的方法を使用してみましょう。

  magick man.gif -threshold 50% +depth \
          -define debug=true -morphology IterativeDistance:-1 Chebyshev \
          chebyshev_gradient.png


magick identify -format 'Maximum Distance = %[max]' chebyshev_gradient.png magick chebyshev_gradient.png -auto-level chebyshev_gradient.gif rm chebyshev_gradient.png
[IM Output]
[IM Text]
[IM Text]
Iterative Distance」形態学的方法は、値の変更が見られなくなるまで距離カーネルを繰り返し適用することで距離を計算します。

これは、画像全体にわたって距離を設定するために2パスメソッドを使用する、より一般的な「Distance」メソッドよりもはるかに遅いです。ただし、「Distance」メソッドの冗長な出力ははるかに面白くありません。

冗長フラグをオンにしたため、コマンドは、各反復(パス)で操作によって変更されたピクセル数(すべての白いピクセル)を出力します。次に、結果を調整(正規化)して、結果の勾配を見ることができる画像にする前に、生成された「最大」距離(「1400」)を抽出しました。「1400」の最大距離は、画像の中で最も明るいピクセルの値です(実際には、そのような4つのピクセルのクラスタです)。この情報は、この距離カーネル(メトリック)の最も重要な結果であり、この形状に収まる最大の正方形のサイズを表しています。具体的には、14ピクセルの半径、または約(R-1)*2+1 => 27ピクセル/辺の正方形であり、それらの4つの最大ピクセルを中心としています。このカーネルのすべての距離単位は常に「100」の倍数であるため、この最終的な距離値は常に「100」の倍数であり、分数成分を持つことはありません。基本的に、このカーネルは整数距離を生成し、距離情報の損失なしに、このカーネルで単純な「1単位」のscaleを使用できます。ImageMagickのQ8バージョンを使用している場合、または非常に大きな画像に適用する場合は、これが推奨されます。
図形の「脚」の間の勾配の拡大図を示します。これは、生成された距離勾配の特徴を強調しています。

  magick chebyshev_gradient.gif -crop 25x20+39+69 +repage \
          -scale 500% chebyshev_magnify.gif
[IM Output]
ご覧のとおり、「Chebyshev」距離カーネルは、非常に正方形のような勾配を生成します。これは、この単純な形式の距離メトリックの特定の特徴であり、距離カーネル自体の正方形の性質を直接反映しています。上記はまた、図の「腹部」の上部近くに4つの最大距離ピクセルを示しています。これらの4点のいずれかに正方形を中心にすることで、図形に完全に含まれる最大の奇数サイズの正方形を生成できます。ただし、そのような「ピーク」が複数ある可能性があることに注意してください。

マンハッタン(タクシー)距離カーネル

Manhattan」距離カーネルは、最も近いエッジまでのX値とY値を加算することで距離を測定します。これは基本的に、ニューヨークのマンハッタンのような大都市の道路でタクシーが移動する場合のような、グリッド状の動きに制限されている場合に移動する必要がある距離です。このため、この尺度に対する他のより一般的な名前は「タクシー」または「市街地ブロック」距離メトリックです。Wikipedia、マンハッタン距離で詳しく知ることができます。これが、実際に生成されるカーネルです…

  magick xc: -define morphology:showkernel=1  -precision 4 \
          -morphology Distance:0 Manhattan     null:
[IM Text]
対角線の値が「200」または中心から2単位になっていることに注意してください。つまり、対角線のピクセルに到達するには、前述のグリッド状の動きで2つのピクセルを通過する必要があります。この結果、対角線は予想よりも大きくなる傾向があり、最終的な距離測定も大きくなる傾向があります。もう一度、この「メトリック」を使用して最大距離と「距離勾配」画像を抽出してみましょう。

  magick man.gif -threshold 50% +depth \
          -morphology Distance Manhattan      manhattan_gradient.png


magick identify -format 'Maximum Distance = %[max]' manhattan_gradient.png magick manhattan_gradient.png -auto-level manhattan_gradient.gif rm manhattan_gradient.png
[IM Output]
[IM Text]
今回は「Iterative Distance」を使用しませんでした。使用したとしても、変更されたピクセルの総数は正確ではありません。「Chebyshev」カーネルのみが、ピクセル距離を一度だけ設定します。画像の最終的な最大距離が「1700」距離単位ではるかに大きくなっており、形状内の最大ピクセルがエッジから17ピクセル離れていることに注意してください。この距離カーネルも「整数」カーネルであるため、情報の損失なしにscaleを「1単位」に設定できます。
これが勾配の拡大図です。

  magick manhattan_gradient.gif -crop 25x20+39+69 +repage \
          -scale 500% manhattan_magnify.gif
[IM Output]
ご覧のとおり、「Manhattan」距離カーネルは、ダイヤモンドのような勾配を生成しました。これは基本的に、実際のカーネル値に反映されているように、この単純な距離メトリックを表しています。

八角形距離カーネル

Octagonal」距離カーネルは、他の2つとは少し異なります。まず、端のピクセルに対してマンハッタン距離を生成し、次に端から2単位離れたピクセルに対してチェビシェフ距離を使用することによって作成されます。その後、3単位離れたピクセルの距離にマンハッタン距離を使用するといったことを繰り返します。その結果、2つのより単純なカーネルを使用した距離の「インターリーブ」または「平均化」が得られます。このカーネルは2つの整数距離カーネルのインターリーブに基づいているため、整数距離カーネルでもあります。「1単位」のスケールを使用して、より低品質のImageMagickバージョンや非常に大きな距離測定に対してより小さな値を生成できます。距離の形状も2つのカーネルの混合であるため、「八角形」形状のカーネルに相当するものを生成します。実際に生成されるカーネルを以下に示します…

  magick xc: -define morphology:showkernel=1  -precision 4 \
          -morphology Distance:0 Octagonal     null:
[IM Text]
カーネルの最小サイズとデフォルトサイズは半径2で、5x5ピクセルのカーネルを形成することに注意してください。このわずかに大きいカーネルは、カーネルの「インターリーブ」を生成するために必要です。全体的な距離は、真の距離よりもわずかに小さくなるのが一般的です。ここでは、最大距離を再び計算します…

  magick man.gif -threshold 50% +depth \
          -morphology Distance Octagonal  octagonal_gradient.png


magick identify -format 'Maximum Distance = %[max]' octagonal_gradient.png magick octagonal_gradient.png -auto-level octagonal_gradient.gif rm octagonal_gradient.png
[IM Output]
[IM Text]
1500」という結果は整数距離であり、実際には小さすぎるチェビシェフ距離と大きすぎるマンハッタン距離の中間にあります。しかし、一般的に、形状の中心までの実際の距離に合理的に近い値でありながら、「整数」値を維持します。
これが勾配の拡大図です。

  magick octagonal_gradient.gif -crop 25x20+39+69 +repage \
          -scale 500% octagonal_magnify.gif
[IM Output]
脚の隙間の上部に形成された「八角形」の距離がはっきりとわかります。また、対角線は厚い対角線と細い対角線のインターリーブを使用して生成されたこともわかります。

分数八角形距離カーネル

名前付き距離カーネルは提供されていません。しかし、これは現在研究している距離カーネルのシーケンスにうまく適合します。八角形の形状を使用して、別のタイプの整数距離カーネルを生成できます。ただし、この場合の整数距離はピクセルあたり2単位の値を使用するため、実際に生成された距離値を半分にする必要があり、生成された小さな整数から分数値が生成されます。これが「分数八角形」という名前の由来です。これを行うには、隣接するピクセル間の整数距離を2、対角線を3にします。
'3: 3,2,3
    2,0,2
    3,2,3'
「半整数」を生成できるため、使用できる最小スケールは「2単位」です。そして、「ナイトの移動」ほど正確ではありませんが、うまく機能します。このカーネルの八角形は、前のカーネルが生成する「平らな面」ではなく、直交方向に「点」を持っています。これは次の「ナイトの移動」カーネルとは完全に同じではありませんが、ある種の「ほぼ整数」形式の「knights」カーネルと見なすことができます。前のIM距離カーネルと同じようにスケーリングしたい場合は、このカーネルを使用できます。
'3: 150,100,150
    100, 0 ,100
    150,100,150'
例を以下に示します。

  magick man.gif -threshold 50% +depth \
          -morphology Distance '3:3,2,3 2,0,2 3,2,3' \
          fractional_gradient.png


magick identify -format 'Maximum Distance = %[max]' fractional_gradient.png magick fractional_gradient.png -auto-level fractional_gradient.gif rm fractional_gradient.png
[IM Output]
[IM Text]
34」という結果は整数距離ですが、実際の最大距離の結果17を得るために2で割る必要があります。しかし、これも整数ですが、16.5という分数距離になる可能性があります。距離結果のこの分数的な側面が、ほとんどのカーネルが100単位で定義されている理由であり、純粋な整数距離カーネルから離れるにつれて、後のカーネルでより顕著になります。
これが勾配の拡大図です。

  magick fractional_gradient.gif -crop 25x20+39+69 +repage \
          -scale 500% fractional_magnify.gif
[IM Output]
勾配(結果を注意深く調べると)は八角形です。しかし、共通の距離値を持つピクセルを見つけるのは困難です。形状をより明確に表示するために、上記の画像を取り込み、同じカラー値(赤)で1組のピクセルを塗りつぶしました。

  magick fractional_magnify.gif -fill red -opaque gray53 \
          fractional_magnify_shape.gif
[IM Output]
ご覧のとおり、同じ値のピクセルは一般的に「ナイトの移動」パターンで分離されていますが、八角形を生成する線を形成します。しかし、八角形は八角形距離カーネルから45度回転しています。また、この形状の違いが、最終的な最大距離が大きくなる原因でもあります。本質的に、このように回転したより大きな八角形の方が形状にうまく適合するため、最大距離の結果が大きくなります。使用できるもう1つの分数距離「整数」カーネルはこれですが、距離は2単位ではなく3単位です。つまり、ピクセルサイズで距離を得るには結果を3で割る必要がありますが、これは実際にはあまり優れた除数ではありません。しかし、これは別の八角形タイプの距離尺度です。
'3: 4,3,4
    3,0,3
    4,3,4'
以下のユークリッド(ナイトの移動)距離カーネルも八角形の形状を生成しますが(すべての3x3距離カーネルがそうであるように)、対角線に沿ってできるだけ正確になるように試みます。これは最善の方法ではないかもしれませんが、このタイプの最も数学的に論理的な八角形距離カーネルです。

チャンファー距離カーネル

名前付き距離カーネルは提供されていません。しかし、これは現在研究している距離カーネルのシーケンスにうまく適合します。「チャンファー」距離カーネル(まだ実装されていません)は、距離行列の塗りつぶしに使用する数字(通常は整数)を使用して定義されます。たとえば、上記のように、任意の3x3「八角形」タイプの距離カーネルを定義するために2つの数字を与えることができます。以前の整数カーネルの定義を以下に示します。
チェビシェフ チャンファー:1,1
マンハッタン チャンファー:1,2
分数八角形 チャンファー:2,3  /2
分数八角形代替 チャンファー:3,4  /3
これらのカーネルはすべて半径1の単純なカーネルです。与えられた値は、使用する実際の「距離スケーリング」値と見なすことができます。ただし、前の整数八角形カーネルを定義するには、3つの数値の半径2チャンファーカーネルが必要であることに注意してください。最もよく知られているチャンファーカーネルは、半径2のカーネル「チャンファー:5,7,11」であり、非常に正確な距離を生成し、整数距離値も生成するため、Q8ユーザーに適しています。伝統的に、カーネル(チャンファー5,7,11)は…の形をしています。
'5:  -   11   -   11   -
    11    7   5   7    11
     -    5   0   5    -
    11    7   5   7    11
     -   11   -   11   -'
または、上記に20を掛けると、距離カーネルでImageMagickによって通常使用されるのと同じピクセル距離スケーリング(100)が生成されます…
'5:  -   220   -   220   -
    220  140  100  140  220
     -   100   0   100   -
    220  140  100  140  220
     -   220   -   220   -'
カーネルがすべてのカーネル距離を実際には塗りつぶしていないことに注意してください。これは、既に提供されている他の値からそれらの値が距離を取得するためです。つまり、距離カーネルを完全に定義するために、2次元配列全体を塗りつぶす必要はありませんが、通常は処理を容易にするために実行されます。私の研究で見つけた他の既知のチャンファーカーネル(整数値のみを使用)のリストを以下に示します。
チャンファー:3,4  /3
チャンファー:5,7,11  /5
チャンファー:99,141,221  /100
チャンファー:987,1414,2206  /1000
チャンファー:12,17,27,38,43  /12
[diagram]
5つの値を配置して半径3チャンファーカーネルを定義する方法
上記の表で強調表示されているカーネルは、最もよく知られており、一般的に使用されているチャンファー距離カーネルです。小さな整数値のみを使用して画像を生成するため、大きな距離勾配画像は精度を失うことなく保存できます。また、非常に正確であり、ほとんどすべての考えられる目的には十分です。ボーナスとして、距離の結果は、正規化されたときに単一の桁の小数部分のみを生成し、再帰的な小数位を生成しません。これが、多くの画像処理パッケージでよく選択される理由でもあります。「チャンファー:5,7,11」は、デフォルトの「チャンファー」距離カーネルと見なす必要があります。

ユークリッド(ナイトの移動)距離カーネル

Euclidean」カーネルは、正確な浮動小数点距離数値を使用して生成されます。しかし、ImageMagickの非HDRIバージョンでこれを使用するには、分数対角線距離を使用する必要があります。たとえば、約1.4142距離単位の値を持つ2の平方根の値を持つ対角線などです。これを機能させるために、距離は(上記のすべてのカーネルと同様に)100の値でスケーリングされ、分数パーセンテージ距離が生成されます。それが生成するデフォルトのカーネルを以下に示します…

  magick xc: -define morphology:showkernel=1  -precision 4 \
          -morphology Distance:0 Euclidean    null:
[IM Text]
デフォルトの半径1を使用すると、精度の点では以前のカーネルよりも大幅に向上しますが、依然としていくつかの制限があります。基本的に、45度の対角線と直交(XとY)の移動に関して距離を提供します。つまり、距離はある種のチェスの「ナイトの移動」に似ています。デフォルトの「Euclidean」または「ナイトの移動」カーネルを使用して作成された最大距離と「距離勾配」画像を以下に示します。

  magick man.gif -threshold 50% +depth \
          -morphology Distance Euclidean    knight_gradient.png


magick identify -format 'Maximum Distance = %[max]' knight_gradient.png magick knight_gradient.png -auto-level knight_gradient.gif rm knight_gradient.png
[IM Output]
[IM Text]
この特定の形状の場合、ご覧のとおり、「1700」距離単位の距離値も得られます。通常、結果は、より小さい「チェビシェフ」距離またはより大きい「マンハッタン」距離の間の分数距離になります。「100」の単純な倍数であり、「マンハッタン」距離と同じであることは、単なる偶然です。ピクセルまでの実際の距離は、実際には対角線距離と直交(軸)距離の合計です。つまり、完全なユークリッド距離ではありませんが、可能な限り最小の距離カーネル(半径1)を使用して最も近い距離です。
形状の「脚」間の勾配の拡大図を以下に示します。

  magick knight_gradient.gif -crop 25x20+39+69 +repage \
          -scale 500% knight_magnify.gif
[IM Output]
ご覧のとおり、勾配ははるかに丸みを帯びた外観を持ち、整数距離カーネルで得られる「玉ねぎ状の」レベルまたは「段差」効果がありません。これは、各ピクセルがエッジからの個別の分数距離を割り当てられる可能性が高いためです。しかし、勾配の最終的な形状は実際にはほぼ「八角形」ですが、前の「八角形」距離カーネルで得られるような上部と下部に平らな面があるのではなく、コンパスの針のような点があります。一般的な距離作業(「フェザリング」など)では、このデフォルトの「Euclidean」または「ナイトの移動」カーネルは良好な結果を提供します。ただし、「整数」距離が得られないため、距離スケール係数「1」を使用して使用できず、Q8バージョンのImageMagickでは使いにくいものになります。

より大きなユークリッド距離カーネル

生成された「Euclidean」カーネルの「半径」を増やすと、さらに正確な「ピタゴラス」または真の「ユークリッド」距離尺度が生成されます。半径が大きいほど、結果の精度が高くなりますが、形態学的「距離」メソッドの実行には時間がかかりますが、必要な反復回数は少なくなります。ただし、半径4を超えると、精度は向上しなくなりますが、速度は大幅に低下します。非常に大きな「Euclidean」カーネルを使用して精度を向上させる例については、以下のアンチエイリアスされた形状を使用した距離を参照してください。以下は、推奨される半径4を使用して生成されるより大きな9×9カーネルを生成する真の「Euclidean」カーネルです…

  magick xc: -define morphology:showkernel=1  -precision 4 \
          -morphology Distance:0 Euclidean:4     null:
[IM Text]
半径4を使用するもう1つの利点は、カーネルにピタゴラスの定理の三角形が含まれていることです。辺は3、4、5、またはデフォルトのカーネルスケールでは300、400、500単位です。これにより、結果の画像の小数成分の数が減少する可能性がありますが、これはほんの小さな効果です。それでも、より高い精度のためには論理的な選択です。その適用例を以下に示します…

  magick man.gif -threshold 50% +depth \
          -morphology Distance Euclidean:4     euclidean_gradient.png


magick identify -format 'Maximum Distance = %[max]' euclidean_gradient.png magick euclidean_gradient.png -auto-level euclidean_gradient.gif rm euclidean_gradient.png
[IM Output]
[IM Text]
このより大きな半径の 'ユークリッド' カーネルを使用することで、最終的な最大距離はこれまでで最も正確な最大距離測定になります。また、形状が非常に規則的でない限り、画像内で複数の「最も明るい」ピクセルを取得する可能性が低くなります。
形状の「脚」間の勾配の拡大図を以下に示します。

  magick euclidean_gradient.gif -crop 25x20+39+69 +repage \
          -scale 500% euclidean_magnify.gif
[IM Output]
ご覧のとおり、勾配は「脚の間」の端にほぼ完全な円形勾配を生成します。このカーネルを使用するコストは、上記のように、実行時間がわずかに遅くなることです。

距離カーネルの比較

ここにもう一度、拡大率の並列比較を示します。これは、使用された4つの距離指標それぞれによって生成される非常に異なる勾配を明確に示しています。
[IM Output]
チェビシェフ
(チェス盤)
[IM Output]
マンハッタン
(タクシー)
[IM Output]
八角形
(混合)
[IM Output]
ユークリッド
(ナイトの動き)
[IM Output]
ユークリッド
(radius=4)
ここでは、今度は左下隅に近い単一の黒ピクセルからの距離を取得する別の比較を示します。ピクセルの拡大はありません。

  magick -size 100x100 xc: -draw 'point 20,80'  distance_start.png

  for kernel in chebyshev manhattan octagonal euclidean euclidean:2 euclidean:4
  do
    magick distance_start.png    -morphology Distance $kernel \
            -auto-level  point_$kernel.png
  done
[IM Output]
チェビシェフ
(チェス盤)
[IM Output]
マンハッタン
(タクシー)
[IM Output]
八角形
(混合)
[IM Output]
ユークリッド
(ナイトの動き)
[IM Output]
ユークリッド
(radius=2)
[IM Output]
ユークリッド
(radius=4)
これらの画像は、ピクセルが開始ピクセルに予想以上に近いと考えられる線、およびさまざまなカーネルが複雑になるにつれて滑らかになる方法を明確に示しています。「より近いピクセル」の目に見える線を示さないのは最後だけです。しかし、半径4でもそれらは存在します。このカーネルの場合、線はソースから遠く離れた場所にのみ表示されます。半径7はさらに良い結果をもたらしますが、速度は大幅に低下します。ただし、結果の画像でアーティファクトを回避するために、そのような精度が必要になる場合があります。最初の3つのカーネルのみが整数距離を生成することに注意してください。これは、適切なスケール調整(個々のカーネルの説明を参照)を使用して、ImageMagickのQ8バージョンで使用できます。そして、これらは通常、多くの画像処理パッケージが使用するものです。単一点からの距離の計算については、後ほど制約付き距離の例で改めて検討します。

特別なユーザー定義距離カーネル

提供されている距離カーネルに限定されるわけではありません。「原点」にゼロ値を使用し、その周囲に増加する距離値を使用するというルールに従う限り、他の非常に興味深い距離効果を生成できます。
たとえば、ここでは、右側のピクセルの値を大きくするだけという非常に小さなユーザー定義カーネルを適用します。

  magick man.gif -threshold 50% +depth \
          -morphology Distance  '2x1+0+0: 0,100 ' \
          -auto-level    distance_linear.gif
[IM Output]
ゆっくりと増加する勾配を「リセット」する「脚の間」のギャップの効果に注目してください。
そして、ここでは、両側から距離勾配を作成しますが、各側のスケールは異なります。

  magick man.gif -threshold 50% +depth \
          -morphology Distance  '3x1: 50,0,100 ' \
          -auto-level    distance_sides.gif
[IM Output]
これらは、可能な距離カーネルのバリアントのほんの一例です。他に何か思いついたら、教えてください。画像の仕上がりが悪い場合は、カーネルの原点の設定が間違っているか、原点が「ゼロ」値ではなかった可能性があります。これは、形態距離関数によってチェックされません。

アンチエイリアスされた形状での距離

距離メソッドは非常にうまく機能します。しかし、その機能性の最良のテストは、距離関数を円に適用し、次にシェーディングして、関数によって生成される可能性のある最も小さなエラーでも強調することです。

  magick -size 129x129 xc: -draw 'circle 64,64 60,4' \
          -negate  circle_shape.png

  magick circle_shape.png  -morphology Distance Euclidean:4 \
          -auto-level cone_distance.png

  magick cone_distance.png -shade 135x30 -auto-level \
          +level 10,90%  cone_distance_shade.png
[IM Output] ==> [IM Output] ==> [IM Output]
上記からわかるように、「円錐形」に見える結果が得られますが、滑らかな「円錐」からはほど遠いものです。それは、エッジから始まる放射状の隆起のネットワークで覆われています。シェーディングされた円錐のエッジを注意深く見ると、円錐は元の形状の滑らかな円形ベースを持っていないことがわかります。「エイリアシング」または「階段状」になっており、これらの「ステップ」が距離関数によって反映されて、見られる放射状の隆起が形成されています。問題は、距離メソッドが、滑らかな外観を与えるためにエッジの周りに円が使用する小さな「グレー」のアンチエイリアシングピクセルについて何も知らないことです。実際、任意の「グレー」ピクセルは、一般的に、アンチエイリアシングされた部分的なエッジピクセルを表すのではなく、全体のピクセルとして考えられています。
何らかの方法でこれらのグレーのエッジ値を結果に含める必要があります。これは、距離メソッドを適用する前に、前処理ステップを使用して行われます。

  magick circle_shape.png  -gamma 2 +level 0,100 -white-threshold 99 \
          -morphology Distance Euclidean:4   -auto-level \
          -shade 135x30 -auto-level +level 10,90%   cone_antialiased.png
[IM Output]
行われたのは、まず、ピクセルのどの部分が円の境界内にあったかを示す表現から、ピクセルが円の端からどれだけ離れていたかを示す表現に、すべてのグレーのピクセルをマジックすることでした。結果からわかるように、ほとんどすべての階段状のエッジエラーが修正されています。見えている最終的なエラーは、エッジから離れた場所にのみ発生し、「円錐」の中心に向かってより目立つようになります。それらは、距離関数の反復によって引き起こされます。ユークリッド距離カーネルのサイズである4ピクセルごとに繰り返し行われます。そのため、小さな不正確さは、エッジから離れるほど強調されます。
これはほとんどの場合問題ではありませんが、より大きなユークリッドカーネルを使用して、より正確で滑らかな結果を得ることで、これらの小さなエラーを削減したり、排除したりすることもできます。ただし、これには生成に時間がかかります。

  magick circle_shape.png  -gamma 2 +level 0,100 -white-threshold 99 \
          -morphology Distance Euclidean:7   -auto-level \
          -shade 135x30 -auto-level +level 10,90%   cone_improved.png
[IM Output]
結果は、アンチエイリアシングされた、または滑らかな形状に対するほぼ完璧な距離関数です。ここでは、前のセクションの2つのユーザー定義距離カーネルを使用した別の例を示します。

   magick circle_shape.png -gamma 2 +level 0,100 -white-threshold 99 \
           -morphology Distance  '2x1+0+0:0,100'  -auto-level \
           circle_gradient.png

   magick circle_shape.png -gamma 2 +level 0,100 -white-threshold 99 \
           -morphology Distance  '3x1:50,0,100'  -auto-level \
           circle_ridge.png
[IM Output] [IM Output]
アンチエイリアシングされたピクセルに対する特別な処理がない場合、上記は画像全体にこのような滑らかな勾配を生成しません。現状では、元の形状の「形状」を復元する必要があります。

距離を使った形状のフェザリング

上記のテクニックは、形状のアルファチャンネルに適用して、オブジェクトを適切に「フェザー」することができます。たとえば、ここでは、形状オブジェクトの周囲に10ピクセルの「スムーズな」フェザーがあります。

   magick rose_orig.png \
           \( +clone -fill black -colorize 100% \
              -fill white -draw 'circle 114,75 110,2' \
           \) -alpha off -compose CopyOpacity -composite \
           -trim +repage rose_shape.png

   magick rose_shape.png \
           \( +clone -alpha extract -virtual-pixel black \
              -gamma 2 +level 0,100 -white-threshold 99 \
              -morphology Distance Euclidean:4,10! \
              -sigmoidal-contrast 3,0% \
           \) -compose CopyOpacity -composite \
           rose_feathered.png
[IM Output] ==> [IM Output]
これは、より単純なぼかしフェザーテクニックとは異なり、すべてのエッジを正確に保持します。上記をアルファチャンネルに対して直接適用することもできますが、一部の演算子は透過チャンネルを「アルファ値」としてではなく「不透明度値」として扱います(具体的には「-white-threshold」演算子)。そのため、最終的な画像にマージする前に、グレースケール画像として処理するためにアルファチャンネルを抽出しました。特別な距離カーネルは、形状のエッジの近くに十分な距離勾配を生成するために、4ピクセルのユークリッドカーネルを3回反復します。「-level」演算子は、それをエッジ( '0')から形状内10ピクセル( '1000'単位)までの線形勾配に変換します。「-virtual-pixel」設定も提供され、長方形の画像コンテナのエッジに触れる形状は、透過性で囲まれていると見なされます。この場合の距離関数の結果は、「線形ランプ」または「ベベル」であり、いくつかのシャープな効果を生み出すことができます。そのため、小さな「-sigmoidal-contrast」修正によって、この透過から不透明への遷移をスムーズにすることができます。強度(上記では '3')が高いほど、エッジでのフェザーはシャープになります。フェザーを透過性にスムーズにテーパリングさせたい場合は、上記のコードの '0%' を '50%' に置き換えて、シグモイド曲線の「肩」を10ピクセルのフェザーの中央に配置します。 **ビットマップ形状フェザー**形状がGIF画像や画像マスクなどからのビットマップの場合、上記のフェザー操作を簡素化できます。たとえば...

  magick figure.gif -channel A -virtual-pixel transparent \
          -morphology Distance Euclidean:4,3!  boolean_feathered.png
[IM Output] ==> [IM Output]
重要な変更点は、距離関数の前処理と後処理がはるかに少ないことです。単に '3!' を使用して特別な距離単位を指定できます。これにより、形状のエッジの周囲に3ピクセルの線形勾配が生成されます。このタイプのフェザー(より大きな「線形フェザー」)の別の例は、サムネイル、ソフトエッジで見ることができます。上記で「-sigmoidal-contrast」演算子を使用して、より大きなフェザーをスムーズにすることができますが、現時点では透過性を「マット」値としてではなくアルファ値として処理することに注意してください。そのため、前のソリューションの '05' の代わりに '100%' の値を使用する必要があります。ビットマップ形状の場合、「-blur 1x0.7」をアルファチャンネルに適用して、わずかにスムーズにした後、上記のより複雑な距離フェザーをそれらの結果に適用する方が良い場合があります。

条件付きまたは制約付き形態学

ここでは、繰り返し行われる形態学演算が画像の特定の領域または領域に制限または制限される手法について説明します。基本的に、特定の制限または関心領域を超えて「オーバーフロー」したり、成長したりしないようにするために使用できるテクニックです。これには一般的に何らかの種類の「マスク」画像が必要であり、通常はライトプロテクトマスクを使用して、更新されるピクセルを制限します。

条件付き膨張

ご存じのとおり、膨張形態学メソッドは、特定のカーネル近傍に従って特定の形状を拡大します。「**条件付き膨張**」は本質的に同じですが、繰り返し画像に適用されるときに膨張がどれだけ広がるかという制限を設定します。描画塗りつぶしは、ある意味では究極の「条件付き膨張」です。開始点と同じ色である任意の直交(ダイヤモンドカーネル近傍)を単純に塗りつぶします。たとえば、いくつかのディスクのいずれかの単一点を選択し、そのディスクが完全に再着色されるまで条件付きで膨張(塗りつぶし)して、他の形状から分離することができます。

  magick disks.gif -fill red -draw 'color 60,60 floodfill' \
          cond_dilate_draw.gif
[IM Output] ==> [IM Output]
同様に、塗りつぶし演算子を使用して同じことを行うことができますが、開始点がユーザーが提供した「条件付きの色」にも一致する場合のみです。

  magick disks.gif \
          -fill green -floodfill +10+40 white \
          -fill blue  -floodfill +30+50 white \
          cond_dilate_floodfill.gif
[IM Output]
この場合、「緑」の塗りつぶしが「ディスクにヒット」し(そして塗りつぶし)、 「青」の塗りつぶし操作は一致しなかったので、ディスクは塗りつぶされませんでした。このような「塗りつぶし」方法の問題は、ユーザーが提供した単一点からしか膨張できないことです。ただし、非常に高速であり、画像全体で機能します。繰り返しまたは反復された膨張は塗りつぶしと同じですが、複数の開始点を持つことができますが、塗りつぶし操作の制限または境界を理解していません。その影響を制限するには、「開始点」だけでなく、塗りつぶしの「条件付き境界」も提供する必要があります。これを行うには、ライトプロテクトマスク(画像のどの部分がライトプロテクトされているか)を作成します。

  magick disks.gif disks.gif -morphology Erode:7 Diamond disks_big_center.gif

  magick disks.gif -negate disks_mask.gif

  magick disks_big_center.gif -write-mask disks_mask.gif \
          -morphology Dilate:15 Diamond +write-mask disks_big_found.gif
[IM Output] ==> [IM Output]  + [IM Output] ==> [IM Output]
上記では、まず浸食メソッドを使用して、半径7(直径7x2+1 => 15ピクセル)より大きいディスクを見つけました。次に、発見された点を同じ量だけ「条件付きで膨張」させて、見つかったオブジェクトを「完全に」復元します。「条件付き膨張」は、オブジェクトの復元のためにオープンメソッドを使用することとは大きく異なります。そのメソッドは、元のオブジェクトの正確な形状ではなく、カーネルの内部「ダイヤモンド」形状を生成します。また、「奇妙な形状」または「中心からずれた」シードポイントも処理しません。「15」の反復数は重要ではありませんが、オブジェクトを完全に復元するには十分な大きさである必要があります。
基本的な形態学演算を実行する場合、ディスクなどの大きな半径を持つカーネルを使用するよりも、ダイヤモンド正方形などの小さなカーネルと反復回数を使用する方が良いでしょう。

これは、条件付き膨張を行う場合に特に重要になります。大きなカーネルは、複数のオブジェクトを分離するギャップを効果的に「ジャンプ」する可能性があります。

ライトマスクを使用して '-1' または(ほぼ)無限の反復回数を使用しないでください。IMv7形態学は現在、ピクセルが書き込み不可能であることを認識しません。そのため、画像への変更がなくなったことを認識せず、常に変更(書き込まれない変更)を形状のエッジの周りに見ているため、終了しません。

これはIMv7で修正されます。IMv7は、演算子がライトプロテクトされたピクセルに関して少し賢くなることができる主要な内部再構築を提供します。

ここでは、ライトプロテクトマスクを使用することの汎用性の別の例を示します。画像全体を斜めの線が通過するディスクを見つけます。

  magick -size 80x80 xc:black -fill white \
                        -draw 'line 0,0 79,79'   disks_line.gif

  magick disks_line.gif disks.gif \
          -compose Multiply  -composite    disks_line_find.gif

  magick disks_line_find.gif -write-mask disks_mask.gif \
          -morphology Dilate:15 Diamond +write-mask disks_line_found.gif
[IM Output]  + [IM Output] ==> [IM Output]  + [IM Output] ==> [IM Output]
追加のマスキングステップ(乗算合成の使用)に注意してください。これにより、線が実際に通過するオブジェクトのみが「検出」されます。「シードポイント」のカーネル半径内にある線に近く(上記の例では接している)、線に接しているオブジェクトも「膨張」されます。もちろん、「近くのオブジェクト」を含めたい場合は、最初のマスキングステップを行う前に、適切な半径の円形カーネルで線を膨張させて(幅を広げて)ください。これにより、正方形カーネル半径に依存するよりも、「近く」の制御が向上します。要約すると、条件付き膨張は、速度は遅いものの、塗りつぶす対象または「検出」する対象を正確に選択する上でより汎用性のある、複数ポイントの描画塗りつぶしと見なすことができます。

制約付き距離

距離形態学メソッドは、オブジェクト内の点がエッジからどのくらい離れているかを簡単に検出するために使用できます。しかし、オブジェクト内の各点が別の点からどのくらい離れているかを検出するためにも使用できます。たとえば、ここでは、各点が単一の「シード」点からどのくらい離れているか(直線距離で)を検出します…


magick -size 100x100 xc: -draw 'point 20,80' distance_start.png magick distance_start.png -morphology Distance Euclidean \ -auto-level distance_point.png magick -font Casual -pointsize 140 label:D \ -trim +repage -gravity center -extent 100x100 \ -threshold 20% distance_bounds.png magick distance_point.png \( distance_bounds.png -negate \) \ -compose multiply -composite -auto-level distance_direct.png
[IM Output] ==> [IM Output] ==> [IM Output] ==> [IM Output]
点からの距離は、オブジェクトの形状によってマスクされます。これは、私たちが関心のある点のみだからです。問題は、上記の距離勾配が、「直線距離」または「始点」への直接距離を表していることです。その勾配をオブジェクトでマスクしても、それは変わりません。「始点からの距離」に関して、ユーザーが通常望むものとは異なります。形状が島を表している場合、島の端から端まで「直線ルート」を取ろうとすると、かなり濡れてしまうでしょう。実際には、オブジェクト「内」のパスに限定された距離が必要です。つまり、オブジェクト自体によって距離が「制限」され、オブジェクト内で可能な限り最短のパスに従うようにしたいのです。そのため、距離勾配が計算されるときに「進入禁止」領域または画像の背景にまたがって(書き込み)ないように、書き込み保護マスクを設定できます。

  magick distance_start.png -write-mask distance_bounds.png \
          -morphology IterativeDistance:150 Euclidean \
          +write-mask -fill black -opaque white -auto-level \
          distance_constrained.png
[IM Output] ==> [IM Output] ==> [IM Output]
ご覧のとおり、結果は正しい「画像全体の距離」勾配であり、始点からの最大距離(白)が、オブジェクトのギャップを「石を投げる距離」で隔てた島の反対側の端であることを明確に示しています。
通常の距離メソッドではなく、より低レベルの「Iterative_Distance」形態学メソッドを使用したことに注意してください。通常の距離メソッドは、画像全体に適用される特別な2パス高速距離メソッドです。このため、書き込みマスクはピクセルの「行」に沿った動作を制限せず、書き込みマスクの効果はほとんどありません。その結果、「Distance」は、書き込みマスクに関係なく、水平方向のギャップを「飛び越える」傾向があります。つまり、通常の距離メソッドは適切に「制限」されていません。「Iterative_Distance」メソッドは、より単純な基本形態学メソッドのように動作し、ローカル近傍にのみ増分的に適用されます。実際には、「膨張」の勾配形式に近く、真のグレースケール形態学メソッドと密接に関連しています。「Iterative_Distance」メソッドは、より小さな「増分ステップ」で画像を処理するため、書き込みマスクによって「制限」されます。残念ながら、速度もはるかに遅くなります。画像を2パス通過する代わりに、上記では、形態学メソッドへの反復回数で指定されたように、150パスを実行します。この反復回数は可能な限り小さく、画像内で検出される最大距離をカバーするのに十分な大きさにするのが最善です。
書き込みマスクを使用して「-1」または(ほぼ)無限の反復回数を使用しないでください。IMv7形態学は、一部のピクセルが書き込み不可であることを理解しておらず、そのため、画像への変更がなくなった場合でも、形状の端にある「書き込み不可ピクセル」への変更を常に検出するため、中止しません。

これは、演算子が書き込み不可のピクセルを理解し、それらの計算や変更済みとしてカウントするのを避けることで、よりスマートになることができる主要な内部再構築を提供するIMv7で修正される予定です。

最後に、そのようなカーネルは正確ではありませんが、半径が1の距離カーネルを使用したことに注意してください。これは、より大きなカーネルを使用すると、その半径よりも小さいギャップを距離勾配が飛び越える可能性があるため重要です。上記条件付き膨張を参照してください。より高い精度が必要な場合は、使用する距離カーネルよりも小さいギャップがないことを確認する必要があります。これには、画像エッジの急な曲げによるギャップも含まれます。

形状のスケルトンの生成。

建設中
From HIPR2 Morphology
http://homepages.inf.ed.ac.uk/rbf/HIPR2/morops.htm


The skeleton/MAT can be produced in two main ways. The first is to use some
kind of morphological thinning that successively erodes away pixels from the
boundary (while preserving the end points of line segments) until no more
thinning is possible, at which point what is left approximates the skeleton.

The alternative method is to first calculate the distance transform of the
image. The skeleton then lies along the singularities (i.e. creases or
curvature discontinuities) in the distance transform. This latter approach is
more suited to calculating the MAT since the MAT is the same as the distance
transform but with all points not part of the skeleton suppressed to zero.

Note: The MAT is often described as being the 'locus of local maxima' on the
distance transform. This is not really true in any normal sense of the phrase
'local maximum'. If the distance transform is displayed as a 3-D surface plot
with the third dimension representing the gray-value, the MAT can be imagined
as the ridges on the 3-D surface.



Definition??

Morphological Skeleton (by erosion?), (by thinning)

Skeletons are calculated either by repeated thinning,  or by distance
transform, and finding the 'creases', or ridges on the 3d surface (watershed
transform?).

   mat.gif -morphology HMT Ridges           -threshold 0
   mat.gif -morphology HMT LineEnds         -threshold 0
   mat.gif -morphology HMT Ridges\;LineEnds -threshold 0

   mat.gif -morphology HMT Ridges\;Ridges2  -threshold 0

   mat.gif -morphology TopHat Diamond              -threshold 0

   mat.gif -define morphology:compose=Lighten \
              -morphology TopHat '3@:-,1,- -,1,- -,-,-' -threshold 0


One definition of medial axis transform (MAT) uses the intensity of each point
to represent the distance ot the boundary.  That the skeleton was used as
a mask for the distance transform. The distance transform method is more
suited to this, and it is probably faster to calculate than by thinning.

SKIZ (Skeleton by Influence Zones) is a skeleton of the background, the
negative of the operation.  That is, dividing the regions closest to each
foreground object.  (generated by thickening)

Generally a SKIZ is pruned down to simple areas, or basins, by also eroding
end of line segments, unless they are attached to an image edge.

Identifying shape by their skeletons.
   distance between farthest 'end' points,
   number of 'loops' or regions in image,
   number of triple points.


スケルトンまでの距離

画像から生の「形態学的スケルトン」を生成する簡単な方法は、「TopHat」メソッドを距離勾配に適用することです。
たとえば、輪郭を少し滑らかにするために少し開いた後の形状のスケルトンを次に示します。

  magick man.gif \
          -morphology Open  Diamond \
          -morphology Distance  Chebyshev \
          -morphology TopHat Diamond \
          -auto-level    chebyshev_dist_skel.gif
[IM Output]
これは基本的に形態学的スケルトンです。最大限の「正方形」(一般的に「最大球」として知られています)を見つけることができるピクセルのみを示しているため、不完全に見えます。しかし、それでも多くの孤立したピクセルを持つ非常に生の結果です。驚くべきことに、それは機能します。「Open」がないと、形状の輪郭が非常に粗いため、結果は非常に悪くなります。
ユークリッド距離尺度を使用すると、形状のより良いスケルトンが生成されます。

  magick man.gif \
          -morphology Open  Diamond \
          -morphology Distance Euclidean:4 \
          -morphology TopHat Diamond \
          -auto-level    euclidean_dist_skel.gif
[IM Output]
しかし、ご覧のとおり、ノイズも増え、スケルトンはより完全になりますが、多くのグレースケール値で非常に汚れています。
スケルトンの「ヘッド」の拡大図を示し、それがどのように分離したままになっているかを示します。

  magick euclidean_dist_skel.gif -crop 35x28+30+13 +repage \
          -scale 400%   euclidean_dist_skel_mag.gif
[IM Output]
もちろん、上記は閾値処理され、それを生成するために使用された実際の距離勾配を持つマスクとして使用できます。これにより、スケルトンを構成する最大円盤の実際のサイズ(距離半径)を調べることができるため、元の形状を再作成できます。

Autotrace を使用したスケルトン

スケルトン生成の別の方法として、「AutoTrace」プログラムとその特別な中心線オプションを使用する方法があります。印刷とフォント変換に関与しているため、処理には白黒を想定していることに注意してください。例として…

  magick man.gif -negate man_at_prep.pgm
  autotrace -centerline -output-format svg man_at_prep.pgm |\
      magick SVG:-  man_centerline.gif
  magick man.gif man_centerline.gif \
          -compose multiply -composite man_at_skeleton.gif
[IM Output] ==> [IM Output] ==> [IM Output] ==> [IM Output]
生成された中心線は、プロセスのベクトル特性のため、スムーズな曲線の形式であることに注意してください。スケルトンのループにギャップがあり、枝が切断されているため、切断されています。ただし、「autotrace」がどのようにしてこのスケルトンを生成するのかは調べていません。「AutoTrace」の使用例については、SVG出力処理およびラスタからベクトルへのエッジ検出を参照してください。