デジタル化を行うときに発生するノイズには、インパルスノイズや、ガウシアンノイズがあります。インパルスノイズは電源などに乗ってくる雷や、電源のON/OFF、蛍光灯の点滅、自動車エンジンのプラグなどの衝撃(Impulse)によって発生し、ガウシアンノイズは光が足りなかったりセンサーや回路などが高温になった場合に発生します。
背景差分で物体抽出 で作成した画像には、光の映り込みで、白いドットが差分としてでていました。これを、インパルスノイズ(ごま塩ノイズ)の除去テクニックとして有名なメディアンフィルタを使って取れるか試してみましょう。
入力画像
パット見では、よくわからないので、わかりやすく記載すると白いノイズはコレです。
仕組みの説明
メディアンフィルタは、インパルスノイズの除去で利用されます。中央にある画素の値を、まわりの画素の平均値で入れ替えるフィルタです。そのため白いドットがごま塩のように存在している場合、まわりの画素の平均値、例えば3×3ピクセル(アパーチャーサイズが3)の黒0で囲まれたの中央値が白1とすると白い部分が0に変わるフィルタになります。
※RBG値であれば白=255,255,255 ですがわかりやすいように 1 としています。
例えば、
000
010
000
という配列があったとすると 1 の周りはすべて 0 なので平均値は 0 なので、
000
000
000
になります。
フィルタのアルゴリズムを実装する場合は、画像の配列を1つ1つ計算していくのでとても面倒です。
サンプルコード
OpenCVには、cv2.medianBlur というメディアンフィルタ用の関数があります。
なんと1行書くだけで動きます。
アルゴリズムを勉強している人は画像データを配列にぶち込んで自力で実装してみてください。
# -*- coding: UTF-8 -*-
import cv2
if __name__ == '__main__':
# 画像の読み込み
img_src = cv2.imread("diff.jpg", cv2.IMREAD_COLOR)
# フィルタ実行前画像の表示
cv2.imshow('frame',img_src)
# フィルタの実行
ksize=7 # アパーチャーサイズ 3, 5, or 7 など 1 より大きい奇数。数値が大きいほどぼかしが出る。
im_mask = cv2.medianBlur(img_src,ksize)
# フィルタ実行後画像の表示
cv2.imshow('frame_mask',im_mask)
# 実行後画像の書き込み
median_path = './diff_mask.jpg'
cv2.imwrite(median_path,im_mask)
cv2.waitKey(0)
cv2.destroyAllWindows()
実行結果
ちゃんと白いドットがなくなりました。
マウスもギザギザが少なくなって若干スムーズな画像となりました。
参考資料