rawpyでPython現像その20(noise thr)

python

 rawpyの現像関数、postprocess関数の引数のnoise thrに関して確認します。

 postprocessに関しての詳細はこちら

 ドキュメントにはウェーブレットノイズ除去の閾値とだけあります。floatで指定するようです。アルゴリズム的には世に広く解説があります。指定する値のスケールが分からないので、調べてみます。

ウェーブレットノイズ除去

 あまり詳しく解説しません。というかできません。色々調べた結果、式がいっぱい出てきてよくわからなかったので。ウェーブレット変換によるノイズ除去でググるとたくさん解説が出てきます。

 感覚的な理解としては、ウェーブレット変換した高周波成分に対して、閾値処理してその閾値より小さい成分はノイズとみなし、0に落とす。その後逆変換して画像に戻す。という比較的ダイナミックなノイズ除去手法の様に読めました。比較的オーソドックスなノイズ除去手段です。弱めるではなく、0に落とすというあたりが潔いです。

 この閾値を大きくすれば、振幅の大きいノイズも除去される代わりに、画像の実エッジもなまる。という関係になりそうです。細かいテクスチャはつぶされそうです。が分かりやすいエッジは残りそうです。

 被写体を見ながら閾値は決める必要がありそうです。髪の毛や、木々の葉っぱ等のディテールは気にした方がよさそうです。ノイズ除去処理のトレードオフの基本ですね。処理は重そうです。

noise_thr

 今回の処理は、以前確認したメディアンフィルタの適応回数を指定する median_filter_passes や、 fbdd_noise_reduction のような色ノイズ除去を行うものではなく、いわゆるノイズ全般を除去してくれるオプションのようです。

 また、確証はないですが、デモザイキング前の信号に対して行っている気がします。というのも同じ閾値でデノイズした結果、 half_size オプションを指定してもしなくても結果が同じような印象になりました。つまり、デモザイクして解像度が上がった状態でウェーブレット変換してない気がします。(解像度が異なれば、同じノイズが同じ周期で同じような振幅にはならない気がします。)ただウェーブレットが何たるかを深く理解していないので、勘違いかもしれません。(センサノイズであればデモザイク前が適切な気がします。)

 ただこの値どの程度の値を入れればよいのかわからないです。レンジもよくわかりません。ウェーブレット変換した後の値のレンジがどのようになっているか次第のような気がします。float指定だし、量子化された離散値ではないということになるのでしょうか?

実験

 というわけで実験してみました。その結果どうやら100刻みくらいで値を探せばよさそうな気がします。1刻み、10刻み、100刻みでデノイズしてみましたが、ソース画像の画素数にもよるかもしれませんが、1、10ではその変化の様子が視認できませんでした。ちなみに0を指定すると、指定しないのと同じ結果になりました。(デフォルトのNone指定相当でした)

 ウェーブレット変換後の量子化がいくつか?ってところですかね?ちなみに65535を指定した時と、70535を指定した時で画像に違いがあるので、16bitってことはなさそうです。画像はボケボケだったので実用的な数値ではないのでこれ以上は調べませんでしたが。

 結果が以下の通りです。

 値を0から100刻みで800まで振った結果です。これくらいの刻みなら変化の様子が見た目で分かりますね。平坦部で同一領域のヒストグラムから分散を出してみましたが、じょじょに数値が小さくなっていくことも確認できました。(ノイズなしの原画像がないのでPNSRは出せないですが。)

 エッジを残しながら、キレイにノイズが取れています。色ノイズに限ってないと思います。

 コードとしてはこんな感じ、100刻みで値を変化させています。

import rawpy
import cv2

raw = rawpy.imread(filename)    
for i in range(9):
    img = raw.postprocess(half_size=True,
                  demosaic_algorithm=rawpy.DemosaicAlgorithm.LINEAR,
                  no_auto_bright=False,
                  bright=1.5,
                  use_camera_wb=True,
                  noise_thr = 100.0*i
                  )

    fname = 'python\\raw\\img_' + str(i) + '.tif'        
    cv2.imwrite(fname,img[:,:,[2,1,0]])

 この結果だけ見るとnoise_thrは大きいほど結果良好に見えますが、やはり800まで行くと、別のデータでは、髪の毛はぺったぺたになってしまいました。

 髪止めのピンはキレイにエッジが残っていますが、髪の毛はぺったぺたです。適切に閾値を探す必要はありそうです。

まとめ

 noise_thrで指定した数字が大きいほど、センサ起因で発生するランダムノイズが除去された画像になる。またこの処理の対象とするノイズは、色ノイズに限らない。ただし適切な値にしないと被写体のディテールが失われる。値は100刻みくらいで、適切な値を追い込んだ方がよさそう。

 ウェーブレットがどうのとか、そんな話ではなく、まぁ一般的なデノイズのトレードオフですね。

python現像
スポンサーリンク
キャンプ工学

コメント

タイトルとURLをコピーしました