[Python][OpenCV] ノイズ除去する画像処理手法 – Closing(クロージング)

 今回は2値画像の隙間ノイズ除去、空いた個所を補完、画素値1の部分同士を結合する効果のあるClosing(クロージング)という画像処理手法の解説をします。

 クロージングは主にキズや異常の検出などに用いることができます。

クロージング(Closing)の特徴・効果


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

 2値化した画像の点々の隙間ノイズ(画素値0のノイズ)を除去、物体の隙間を補完、別れた部分を結合する役割を持ちます。

 2値化でのみ使えて、物体のノイズ除去、隙間補完、結合という効果のため、キズや異常個所の検出に非常に役立ちます。

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

クロージング(Closing)の仕組み


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

 クロージングはざっくり言うと以下の流れです。最後に画像を縮小するからクロージング(Closing)という手法名です。

  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になる部分の幅が広がり物体の膨張・拡大ができます。

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


 画素値0の点々のノイズを除去、物体の隙間を補完、別れた部分の結合ができます。

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

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

 このままだと白いキズらしき箇所に黒い点々があったり、細かいキズが離れています。

 クロージングを行うことで右の画像のように黒い点が消えて細かいキズが結合されるようになります。

 カーネルサイズを上げるとより結合しやすくなります。ただし、縮小が大きくなるため輪郭が荒くなってしまいます。

 クロージングでキズ同士結合できて黒い点々ノイズは除去できたが、白い細かい部分が残っています。こういう箇所はオープニングを組み合わせることで除去できます。

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

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

Python/OpenCVを使った実装


 Python、OpenCVなら1行で済みます。

import cv2
import numpy as np

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

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


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

コメントを残す

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