一般に、エッジ検出は沸騰して、勾配値の高い画像の領域を検出します。
私たちの場合、勾配を画像関数の微分として大まかに見ることができるので、勾配の大きさは、(隣接するピクセル/テクセルに関して)画像が局所的にどれだけ変化するかについての情報を提供します。
これで、エッジは不連続性の指標となるので、グラデーションを定義したので、この情報で十分です。画像の勾配が見つかったら、それをしきい値に適用してバイナリ値のエッジ/非エッジを取得するだけです。
この勾配をどのように見つけるかは本当にあなたが求めていることであり、私はまだ答えていません:)
たくさんの方法!ここにカップル:)
組み込みシェーダー関数
hlslとglslはどちらも派生関数を提供します。GLSLには、x方向とy方向の勾配情報をそれぞれ提供するdFdxとdFdyがあります。通常、これらの関数は2x2フラグメントのブロックで評価されます。
単一方向に関心がない限り、領域内の勾配がどれほど強いかを示すコンパクトな結果を得る良い方法は、dFdyとdFdyの絶対値の合計以外に何も与えないfwidthです。
特定のチャネルではなく画像全体のエッジに関心がある可能性があるため、画像関数を輝度に変換することができます。これを念頭に置いて、エッジ検出に関しては、シェーダーに次のものを含めることができます。
float luminance = dot(yourFinalColour,vec3(0.2126, 0.7152, 0.0722));
float gradient = fwidth(luminance );
float isEdge = gradient > threshold;
高いしきい値では粗いエッジが見つかり、逆に低いしきい値では誤ったエッジが検出される可能性があります。自分のニーズにより適したしきい値を見つけるために実験する必要があります。
これらの関数が機能する理由は言及する価値がありますが、今はその時間がないので、後でこの回答を更新する可能性があります:)
画面スペースの後処理
これよりも洗練された方法で、画像処理におけるエッジ検出の分野は広大です。必要に応じてエッジ検出を検出するための数十の方法を紹介しますが、ここでは簡単にしてみましょう。興味があれば、さらに多くのオプションを紹介できます。
したがって、アイデアは上記のものと似ていますが、必要に応じて、より広い近傍を見て、周囲のサンプルに一連の重みを使用できるという違いがあります。通常、カーネルを使用して画像に対してたたみ込みを実行すると、結果として適切な勾配情報が得られます。
非常に一般的な選択はSobelカーネルです
これにより、それぞれx方向とy方向の勾配が得られます。
として、勾配から単一の値を取得できます。GradientMagnitude=(Gradientx)2+(Gradienty)2−−−−−−−−−−−−−−−−−−−−−−−√
次に、前述の方法と同じようにしきい値を設定できます。
ご覧のように、このカーネルは中央のピクセルにより多くの重みを与えるので、効果的に勾配+伝統的に役立つ少しの平滑化を計算します(多くの場合、画像はガウスぼかしで小さなエッジを除去します)。
上記は非常にうまく機能しますが、平滑化が気に入らない場合は、Prewittカーネルを使用できます。
(私は急いでいることに注意してください、すぐに画像の代わりに適切なフォーマットのテキストを書きます!)
実は、リアルタイムグラフィックスではなく、画像処理-方法でエッジ検出を検出するためのカーネルとテクニックはたくさんあります。したがって、dFdx / y関数でうまくいくので、より複雑な(意図しない)メソッドを除外しました。 。