PerfectVector
著者: Irene Kim

SVGのエッジ検出:feConvolveMatrixでプレビューする

SVGのfeConvolveMatrixでエッジを表示。アルファや枠の問題を調べ、鮮鋭化カーネルと比較し、元データに実際のパスがあるか確認します。

2 分で読める
目次

SVGのfeConvolveMatrixによるエッジ検出は、色の境界付近の描画ピクセルを変えます。SVG内のPNGからエッジのプレビューを作れますが、編集可能なパスの輪郭は作りません。その後にロゴの編集、線画の準備、ウェブ用アートワークの制作を行う場合は、この違いを明確にしてください。

最初のテストには、既知の図形を持つ小さなグレースケール画像が適しています。対称なエッジ検出カーネルを適用し、アルファを保持して、変更していない元画像と比較します。その後でSVG要素を確認してください。境界が鮮明に見えても、画像がベクター形状になった証拠にはなりません。

条件を固定したエッジプレビューから始める

feConvolveMatrixリファレンスは、畳み込みを入力ピクセルとその周囲のピクセルによる計算と説明しています。この3 × 3のカーネルは、中心の8倍から周囲の8ピクセルを引きます。

-1 -1 -1
-1  8 -1
-1 -1 -1

係数の合計はゼロです。均一な領域では応答がゼロになり、明るさが変わる場所では正にも負にもなります。bias="0"では、負の結果は色の下限で切り捨てられます。そのため、プレビューではすべての境界の両側が均等に表示されるわけではありません。

この例はdivisor="1"を明示しています。divisorリファレンスは、その値による正規化と、係数の合計がゼロのカーネルでの既定値が1であることを説明しています。また、color-interpolation-filters="sRGB"を設定し、プリミティブの既定のlinearRGB処理ではなく、sRGBのチャンネル値を使います。

この完全に自己完結したファイルをedge-preview.svgとして保存し、ブラウザーで開いてください。埋め込みPNGは、不透明な白い紙の上に描いた、独自の48 × 48グレースケールのひし形です。中央は白で、透明ではありません。

<svg xmlns="http://www.w3.org/2000/svg" width="48" height="48" viewBox="0 0 48 48">
  <defs>
    <filter id="effect" filterUnits="userSpaceOnUse" x="0" y="0" width="48" height="48" color-interpolation-filters="sRGB">
      <feConvolveMatrix in="SourceGraphic" order="3" kernelMatrix="-1 -1 -1 -1 8 -1 -1 -1 -1" divisor="1" bias="0" targetX="1" targetY="1" edgeMode="duplicate" preserveAlpha="true"/>
    </filter>
  </defs>
  <image width="48" height="48" href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADAAAAAwCAYAAABXAvmHAAABOklEQVR4nNWZQQ7EIAwDU7+seTlPo1ppTyvRhcQGxYeeGuNpEZT06r13KyxYccGKC1ZcsOKCFRfUA7h7XQD/hldCQGX8G1oFAYXpKKwCAmzDfyHZEGCazYZjQoBltBqKBQGGSTSMEyDSANkQnqxPAbCmgSd8wgDs1cSDflAP1lqT+IYBIuGVENj15FUQUJiOwiogwDSbCcmGAMNkNRwTApniaKjV+/0lB06Ej9T5IA9Ord+rdW2Q53UKKSFYbxiZ4mgo5vQEw0R1ImsT405vZAwIxcKAacckhGpVw/SdAfNIX6gtLslX9P+AokXSAvtJ+EAT3bzYfjgxKNMHJwdn1FPaKju+heSNLeXX6LbWouI8sL25yzyRHWuvM87Ex39wZLoSS+pi3fct9b8+FyssWHHBigtWXDgdIKsHsU1cbk4FPAgAAAAASUVORK5CYII=" filter="url(#effect)"/>
</svg>

フィルター定義が働くのは、画像がfilter="url(#effect)"で参照しているからです。SVGフィルターリファレンスは、定義そのものは描画されないことを説明しています。明示した領域は、この48 × 48の元画像を覆います。別のアートワークでは、領域を個別に確認する必要があります。

ブラウザーテストで変わったこと

独自に作成した六つのサンプルを、Chromeで48と192 CSSピクセルで確認しました。五つのファイルには一つの埋め込みPNG画像があり、パスはありません。六つ目は、独立して手作業で作ったベクター版です。形状の対照例であり、フィルターの適用やPNGのトレースの結果ではありません。

サンプル観察した見た目均一な箇所で読み取った値
SVG内の元のPNG中央と紙が白いグレーのひし形グレーの一色部分:RGBA 64, 64, 64, 255
エッジカーネル、アルファ保持黒い面にエッジ応答があり、大きい表示では輪郭が薄い中央と角:RGBA 0, 0, 0, 255
エッジカーネル、アルファもフィルター処理このテストファイルでは透明な結果中央、角、一色部分:RGBA 0, 0, 0, 0
鮮鋭化の対照例塗られたひし形を保持し、境界のピクセルが変化グレーの一色部分はRGBA 64, 64, 64, 255のまま
エッジカーネル、領域外をゼロ値で処理明るい外枠が出現角:RGBA 255, 255, 255, 255
手作業のパス対照例白い紙の上に、きれいな幾何学的ひし形と内側の開口部パス要素一つ、画像要素なし

RGBAのサンプルは、各SVGを描画した48 × 48のCanvasから読み取りました。画面上のサンプルは、両方のサイズで別に確認しています。これはこの元画像とブラウザーでの観察であり、互換性や見やすさの保証ではありません。ラスターベースのプレビューを拡大しても、よりきれいな輪郭は復元されませんでした。

ピクセル応答と編集可能な形状
グレースケールのピクセルによるエッジ応答のひし形と、独立して描いた編集ノード付きのコーラル色ひし形リングを対比する概念図
模式図:ピクセルのエッジプレビューと編集可能なパスは、異なる表現です。ブラウザーのスクリーンショットや変換結果ではありません。

紙を消さずに、消えた結果を取り戻す

preserveAlphaの既定値はfalseです。この設定では、カーネルはアルファも処理します。不透明なこの入力はすべての場所でアルファが1なので、合計ゼロのエッジカーネルは、均一な色とともに均一なアルファも打ち消します。確認したテストファイルでは結果が消えました。

preserveAlpha="true"を設定すると、色を処理しながら元のアルファを保持します。preserveAlphaリファレンスに、この違いが記載されています。このテストでは、不透明なエッジプレビューに戻ります。また、処理後の色が黒になっても、不透明な紙と白い中央は不透明のままです。アルファを保持しても、背景の削除やロゴの穴の検出は行われません。

プレビューがほぼ黒い場合は、まず既知の均一領域と既知の境界を比較してください。黒は正しいゼロ応答の場合があります。中間調の周囲で符号付きの明るさの変化を確認するには、bias="0.5"を試します。biasリファレンスは、除算後に加えるオフセットを説明しています。これは表示範囲を変えるもので、SVGの形状を変えるものではありません。

アートワークと画像の縁を別々に確認する

最初の比較ではedgeMode="duplicate"を維持します。隣接サンプルが入力範囲外にある場合に、端のピクセル値を延長します。noneはゼロ値のRGBAサンプルを使い、wrapは反対側の端からサンプルを取ります。edgeModeリファレンスでは、これらを異なる規則として定義しています。

不透明な白いカードでは、duplicateだけをnoneに変えると、カードの外周に明るい枠ができました。その境界は画像の長方形のもので、ひし形のものではありません。枠をアートワークの輪郭と扱う前に、フィルターなしのファイルと比較してください。

Filter Effects仕様は、カーネルの基準位置とサンプリング動作を定義しています。ここではtargetX="1"とtargetY="1"で3 × 3のカーネルを中央に置きます。このひな形はkernelUnitLengthを設定していません。どの表示サイズでも隣のサンプルまでが必ずSVGユーザー単位で1になると考えず、納品する描画結果を確認してください。

鮮鋭化は対照例として使い、ぼけの復元とは考えない

塗られたアートワークを維持しながら局所的な変化を強調するには、kernelMatrixだけを次に置き換えます。

0 -1  0
-1 5 -1
0 -1  0

合計は1です。均一なチャンネル値cは、除数1、バイアス0で5c - 4c = cを返します。このテストファイルでは、グレーの一色部分のサンプルは64のままで、境界ピクセルが変わりました。この比較ではpreserveAlpha="true"とedgeMode="duplicate"を保持してください。

鮮鋭化は、必要な境界とともにノイズやハローも強調する場合があります。画像がフィルターに届く前に失われた元の細部は復元できません。拡大プレビューの見た目が悪い場合は、強いカーネルを元画像の解像度の代わりにせず、元画像に戻ってください。

ベクタートレースと呼ぶ前にファイルを確認する

公開しているひな形には、hrefがdata:image/pngで始まる<image>が含まれます。image要素リファレンスは、この要素が表示できるラスターとSVGのリソースを説明しています。ここではメディアタイプが埋め込みラスターを示しており、エッジフィルターをかけてもその要素は残ります。

比較用に、独立して作成したマスターでは、白い長方形の上に次の複合パスを使っています。

<svg xmlns="http://www.w3.org/2000/svg" width="48" height="48" viewBox="0 0 48 48">
  <rect width="48" height="48" fill="white"/>
  <path d="M24 6 L42 24 L24 42 L6 24 Z M24 17 L31 24 L24 31 L17 24 Z"
        fill="#404040" fill-rule="evenodd"/>
</svg>

この座標は別に記述したものです。フィルターをかけた画像から復元したものではなく、ピクセル描画と形状の対照例が、境界のすべてのサンプルで一致する必要もありません。埋め込みラスターの確認ガイドは、ズームだけに頼らず混在したSVGを調べる方法を説明しています。

ウェブ用アートワークでは、フィルターなしのSVGマスターを残し、効果がデザインに役立つ場合にフィルター付き表示用コピーを使います。編集用や製作用のパスには、実際の元の輪郭と内側の開口部を確認してください。線画からSVGへのガイドでは、その形状の作業を扱っています。

元のアートワークがフラットなPNGやJPGで、編集可能な元の図形が必要な場合は、PerfectVectorを使えます。元画像をSVGに変換し、輪郭と内側の開口部を確認して、きれいな結果をマスターとして残してください。エッジプレビューに成功しても、その確認の代わりにはなりません。ベクター化ガイドで、パスの再構築と画像効果の適用の違いを説明しています。

よくある質問

SVGのfeConvolveMatrixによるエッジ検出はベクターパスを作りますか? 作りません。描画ピクセルの効果を計算します。この例の埋め込みPNGは画像要素のままです。編集可能な輪郭には、別に描画またはトレースした形状が必要です。

エッジフィルターでアートワークが消えるのはなぜですか? preserveAlphaを確認してください。既定のfalseではアルファも処理します。この不透明なテストファイルでは、合計ゼロのカーネルにより、確認した結果が透明になりました。アルファを保持すると、不透明なプレビューに戻りました。

preserveAlphaは白い背景を削除しますか? 削除しません。元のアルファを保持します。不透明な白い背景は、処理後の色が黒になっても不透明のままです。背景の削除とパスの再構築は別の作業です。

エッジフィルターが画像の周囲に枠を描くのはなぜですか? edgeModeと入力の長方形を確認してください。不透明な白いカードの外側でゼロ値のサンプルを使うと、明るい外枠ができました。このテストファイルでは、duplicateによる端の処理でその枠を避けられました。

出典

  1. MDN:feConvolveMatrix — 周辺ピクセルによる畳み込みと、既定の色処理。
  2. MDN:divisor — 正規化と、係数の合計がゼロの場合の既定値。
  3. MDN:filter — フィルター効果の定義と適用。
  4. MDN:preserveAlpha — 色だけの処理と、アルファを含む処理。
  5. MDN:bias — 除算後の応答のシフト。
  6. MDN:edgeMode — 端の複製、反対側の参照、ゼロ値による処理。
  7. W3C:Filter Effects、feConvolveMatrix — 基準位置とサンプリング規則。
  8. MDN:image — 参照するラスターとSVGの画像内容。

ブログのその他の記事

PerfectVector

編集しやすい
よりきれいなSVGから始めましょう

クレジットカード不要