[Python][OpenCV] ノイズ除去する画像処理手法 – Opening(オープニング)

 今回は2値化画像の小さいノイズのみを除去する効果のあるOpening(オープニング)という画像処理手法の解説をします。

 オープニングもクロージングと同様、主にキズや異常個所の検出などに用いることができます。

オープニング(Opening)の特徴・効果


 まず前提として2値化した画像にしか使えません。

 2値化画像の中の、画素値が1になっている小さい箇所を他の箇所はそのままに除去することができます。画素値が1のノイズを除去する効果です。

 ある程度検出する部分の候補を絞ったうえで、小さい余計な部分を除去することに役立ちます。

 オープニングと反対の処理をするクロージングは画素値が0のノイズを除去する効果を持ちます。クロージングについてはこちらでまとめています。

オープニング(Opening)の仕組み


 中身に興味がなければ「どういうノイズ除去に使えるか・デメリット」の章まで飛ばしてください。

 オープニングは以下の流れです。最後に拡大するからオープニング(Opening)という手法名です。クロージングとは逆の処理を行っていることが分かります。

  1. 2値化された画像の、値が1の部分をモルフォロジー変換で収縮・縮小させる
    1. ここで小さい箇所を除去する
  2. 1.で収縮・縮小した画像をモルフォロジー変換で膨張・拡大して元の大きさに戻す

 モルフォロジー変換についてはここではざっくりしか説明しません。詳しくは以下のページを参照してください。

https://axa.biopapyrus.jp/ia/opencv/morphology-transformation.html

モルフォロジー変換の収縮・縮小

 収縮・縮小の方は、

  • 全ての値が1のカーネルを用意
  • 全ピクセルでカーネルを使ってAND演算を行う
  • 周辺の画素値がすべて1ならば対象ピクセルを1、そうでなければ0にする

 こうすることで、1になる部分の幅が狭くなり、物体の収縮・縮小ができます。

モルフォロジー変換の膨張・拡大

 逆に膨張・拡大の場合は

  • 全ての値が1のカーネルを用意
  • 全ピクセルでカーネルを使ってOR演算を行う
  • 周辺に1つでも画素値が1のピクセルがあれば対象ピクセルを1、そうでなければ0にする

 こうすることで、1になる部分の幅が広がり物体の膨張・拡大ができます。

どういうノイズ除去に使えるか・デメリット


 画素値1の点々のノイズを他の箇所はそのままで除去することができます。

 今回は以下のような壁にある錆を検出したい場合を考えてみます。

 左の画像はグレースケール + 大津の2値化 + ビット反転した後の画像です。要するに錆っぽい箇所をとりあえず1にした状態。

 このままだと細かいキズ大量にあるため、大きな錆部分が一つの領域として検出できなかったり、検出結果に細かいものが大量に混入してしまいます。

 オープニングを行うことで右の画像のように白い細かい部分が他部分はそのままに除去されてます。

 カーネルサイズを上げるとより大きいノイズを除去できます。ただし、拡大・縮小が大きくなるため輪郭がぼんやりしやすくなります。

 オープニングで白いノイズは除去できたが、白い箇所の中に黒いノイズがあったり、錆が離れたりしています。こういう問題はクロージングを組み合わせることで解決できます。

 以下の画像はクロージング後にカーネルサイズ30のオープニングをした結果です。

 オープニングの前にクロージングを適用すると、以下の画像のように余計な黒いノイズが除去されて、離れていた錆が結合され、はっきりした錆の箇所のみ検出されていることが分かります。

Python/OpenCVを使った実装


import cv2
import numpy as np

img = cv2.imread(ファイルパス)
img = cv2.morphologyEx(img, cv2.MORPH_OPEN, np.ones((15, 15), np.uint8))

2値化以外の画像でも使えるノイズ除去手法


 通常の画像にも使える手法だとメディアンフィルタやバイラテラルフィルタがあります。

 また、ほかにも画像処理関連で色々な技術まとめているのでよかったら見てみてください!

コメントを残す

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