OpenCV 5.0.0
Open Source Computer Vision
読み込み中...
検索中...
見つかりません
🤖 AIによる機械翻訳(非公式) — これは OpenCV 5.0.0 公式リファレンス(英語)を AI (Claude) で自動翻訳したものです。訳に誤りを含む場合があります。正確な情報は 公式英語版(原文) を参照してください。
モルフォロジー変換

目的

本章では、

  • ここでは収縮 (Erosion)、膨張 (Dilation)、オープニング (Opening)、クロージング (Closing) などのさまざまなモルフォロジー演算を学ぶ。
  • ここでは次のようなさまざまな関数を扱う: cv.erode(), cv.dilate(), cv.morphologyEx() など。

理論

モルフォロジー変換は、画像の形状に基づくいくつかの単純な演算である。通常は二値画像に対して実行される。2つの入力が必要で、1つは元の画像、もう1つは構造要素またはカーネルと呼ばれるもので、演算の性質を決定する。基本的なモルフォロジー演算子は収縮 (Erosion) と膨張 (Dilation) の2つである。さらに、オープニング (Opening)、クロージング (Closing)、勾配 (Gradient) などの派生形も登場する。以下の画像を使って、これらを1つずつ見ていく:

image

1. 収縮 (Erosion)

収縮の基本的な考え方は土壌侵食とまさに同じで、前景オブジェクトの境界を削り取っていく(前景は常に白で保つようにするとよい)。では、何をするのか。カーネルが画像上をスライドする(2次元の畳み込みと同様)。元画像のピクセル(1または0)は、カーネル下のすべてのピクセルが1である場合のみ1とみなされ、そうでなければ収縮される(0にされる)。

つまり、カーネルのサイズに応じて、境界付近のすべてのピクセルが除去される。その結果、前景オブジェクトの太さやサイズが減少する、言い換えれば画像内の白い領域が減少する。これは、小さな白いノイズを除去する(カラースペースの章で見たように)、つながった2つのオブジェクトを切り離す、などに役立つ。

ここでは例として、すべての要素が1の 5x5 カーネルを使う。どのように動作するか見てみよう:

import cv2 as cv
import numpy as np
img = cv.imread('j.png', cv.IMREAD_GRAYSCALE)
assert img is not None, "file could not be read, check with os.path.exists()"
kernel = np.ones((5,5),np.uint8)
erosion = cv.erode(img,kernel,iterations = 1)
Mat imread(const String &filename, int flags=IMREAD_COLOR_BGR)
Loads an image from a file.
void erode(InputArray src, OutputArray dst, InputArray kernel, Point anchor=Point(-1,-1), int iterations=1, int borderType=BORDER_CONSTANT, const Scalar &borderValue=morphologyDefaultBorderValue())
Erodes an image by using a specific structuring element.

結果:

image

2. 膨張 (Dilation)

これは収縮のちょうど逆である。ここでは、カーネル下に少なくとも1つのピクセルが '1' であれば、ピクセル要素は '1' になる。したがって、画像内の白い領域が増加する、つまり前景オブジェクトのサイズが大きくなる。通常、ノイズ除去のような場合には、収縮の後に膨張を行う。なぜなら、収縮は白いノイズを除去するが、同時にオブジェクトも縮小させるからである。そこで膨張させる。ノイズは消えているので戻ってこないが、オブジェクトの面積は増加する。これは、オブジェクトの途切れた部分をつなぐのにも役立つ。

dilation = cv.dilate(img,kernel,iterations = 1)
void dilate(InputArray src, OutputArray dst, InputArray kernel, Point anchor=Point(-1,-1), int iterations=1, int borderType=BORDER_CONSTANT, const Scalar &borderValue=morphologyDefaultBorderValue())
Dilates an image by using a specific structuring element.

結果:

image

3. オープニング (Opening)

オープニングは 収縮の後に膨張を行う 処理の別名にすぎない。上で説明したように、ノイズ除去に有用である。ここでは関数 cv.morphologyEx() を使う

opening = cv.morphologyEx(img, cv.MORPH_OPEN, kernel)
void morphologyEx(InputArray src, OutputArray dst, int op, InputArray kernel, Point anchor=Point(-1,-1), int iterations=1, int borderType=BORDER_CONSTANT, const Scalar &borderValue=morphologyDefaultBorderValue())
Performs advanced morphological transformations.

結果:

image

4. クロージング (Closing)

クロージングはオープニングの逆で、膨張の後に収縮を行う処理である。前景オブジェクト内部の小さな穴や、オブジェクト上の小さな黒い点を埋めるのに役立つ。

closing = cv.morphologyEx(img, cv.MORPH_CLOSE, kernel)

結果:

image

5. モルフォロジー勾配

これは、画像の膨張と収縮の差分である。

結果はオブジェクトの輪郭のようになる。

gradient = cv.morphologyEx(img, cv.MORPH_GRADIENT, kernel)

結果:

image

6. トップハット

入力画像とその画像のオープニングとの差分である。以下の例は 9x9 カーネルで行っている。

tophat = cv.morphologyEx(img, cv.MORPH_TOPHAT, kernel)

結果:

image

7. ブラックハット

これは、入力画像のクロージングと入力画像との差分である。

blackhat = cv.morphologyEx(img, cv.MORPH_BLACKHAT, kernel)

結果:

image

構造化要素

前の例では Numpy を使って構造化要素を手動で作成した。これは矩形である。しかし場合によっては、楕円形/円形のカーネルが必要になることがある。そのために OpenCV には関数 cv.getStructuringElement() がある。カーネルの形状とサイズを渡すだけで、目的のカーネルが得られる。

# Rectangular Kernel
>>> cv.getStructuringElement(cv.MORPH_RECT,(5,5))
array([[1, 1, 1, 1, 1],
[1, 1, 1, 1, 1],
[1, 1, 1, 1, 1],
[1, 1, 1, 1, 1],
[1, 1, 1, 1, 1]], dtype=uint8)
# Elliptical Kernel
>>> cv.getStructuringElement(cv.MORPH_ELLIPSE,(5,5))
array([[0, 0, 1, 0, 0],
[1, 1, 1, 1, 1],
[1, 1, 1, 1, 1],
[1, 1, 1, 1, 1],
[0, 0, 1, 0, 0]], dtype=uint8)
# Cross-shaped Kernel
>>> cv.getStructuringElement(cv.MORPH_CROSS,(5,5))
array([[0, 0, 1, 0, 0],
[0, 0, 1, 0, 0],
[1, 1, 1, 1, 1],
[0, 0, 1, 0, 0],
[0, 0, 1, 0, 0]], dtype=uint8)
# Diamond-shaped Kernel
>>> cv.getStructuringElement(cv.MORPH_DIAMOND,(5,5))
array([[0, 0, 1, 0, 0],
[0, 1, 1, 1, 0],
[1, 1, 1, 1, 1],
[0, 1, 1, 1, 0],
[0, 0, 1, 0, 0]], dtype=uint8)
Mat getStructuringElement(int shape, Size ksize, Point anchor=Point(-1,-1))
Returns a structuring element of the specified size and shape for morphological operations.

追加リソース

  1. HIPR2 の Morphological Operations