GLSLで画像のぼかしや平滑化


GLSLで画像処理をする中でぼかした画像を使いくなった。

何を使ってどうしようかなと少し考えたので整理しつつ書いておきます。

ぼかし、平滑化 / blur, smoothing

処理したい座標の画素値と周囲の画素値を使ってノイズをとると考えます。

取ってくる画素値の範囲や各値の重みを変えることで色々なフィルタになります。

 

まずはシンプルに注目点と8近傍の平均。

gl-reactでは処理する点(注目点)がuvで与えられます。

これは正規化されているので解像度を与えて除算することで隣接点を取ります。

画素取得の境界値超えも処理されるので無視しています。

 

8近傍から拡張することを考えます。

GLSLではfor文の条件で変数値を使えないので若干変な処理になってます。

これは見ての通り最大21×21平均まで対応できます。無駄が多いなぁ。

 

ガウシアンやバイラテラルフィルタのような実装で重みの異なるフィルタを簡単に変更できるように実装するにはどうすればいいんだろう。

ベクトルも行列も4次元までしかないしそれぞれ1から書かないといけなさそう。

面倒なので時間がかかりそうなのでこれはやめておきます。

 

ノイズ除去の方法で注目画素ごとに違う処理をするものとしてk近傍やメディアンフィルタなどがあります。外れ値がある場合に有効なやつです。

これらは範囲内の画素値のソートが必要になるんですがテストだしバブルソートで済ませています。for条件の制限のせいでさらに負荷が増えてますが。

また比較する画素値はRGBのどれかを使ってもいいんですが、基本的なグレースケール化をしています。

ちなみにtextureBlurの返値をcs[0](最低値)にすると収縮フィルタ(erode)、cs[8](最大値)にすると膨張フィルタ(dilate)になります。

左から収縮、メディアン、膨張

 

あとは高速フーリエ変換(FFT)してノイズを除去するなどもありますが、GLSLで書ける気がしないのでなにか見つけたら追記することにします。

先鋭化 / Sharpening

ぼかした画像を使って逆にくっきりした画像を作ることもできます。

いわゆるアンシャープマスクです。

8近傍のtextureBlurの返値部分をこう考えるとそのまま先鋭化になります。

 

左から元画像、ぼかし、差分、先鋭化です。髪の部分は特にわかりやすい。

 

先鋭化は同じようにラプラシアンフィルタなどのエッジ検出結果を元画像に足すなどしても可能です。


コメントを残す

メールアドレスが公開されることはありません。