Python OpenCV 空間フィルタ #1

株式会社リュディアです。Python を使った画像処理として OpenCV を使った方法をまとめていきます。

基本的な空間フィルタによる画像処理は大きく 2 つに分類できます。1 つは画像中の境界を抽出する処理、もう 1つは画像を滑らかにするものです。いずれも空間フィルタリングという処理を行うことが多いです。

まず画像の中から境界を抽出する処理をまとめながら画像処理に必要な用語もまとめていきます。画像の中から境界を抽出する処理を境界抽出エッジ抽出と言います。

今、入力画像のある画素を処理して出力画像の対応する画素を生成することを考えます。ある画素のことを基準画素中心画素と呼びます。空間フィルタリングを行う際には基準画素だけでなく周辺の画素の情報も考慮して変換処理を行い出力画素を求めます。この変換処理を行うための係数、または係数行列のことをカーネルと呼びます。カーネルは 3x3画素、5x5画素、7x7画素などのサイズであることが多いです。

フィルタリングとはフィルター処理を行うことフィルタ処理は実際にはカーネルと原画像の演算処理を行い出力画像を求めることになります。いろいろなフィルタ処理がありますが、フィルタ処理毎に異なるカーネルを使うことになります。では具体例を見てみましょう。

エッジ抽出で用いる最も基本的なフィルタである微分フィルタについて説明します。微分フィルタは輝度情報に対して画像の横方向、縦方向のそれぞれに変化量を抽出するフィルタリング処理です。以下の例を見てください。

画像1

青で囲った画素を注目画素とし、X方向の画素の変化量を調べたいとします。つまり 20 が 65 になっている変化を調べたいわけです。どのようなカーネルを用意すればよいでしょうか。以下の図を見てください。

画像2

最初の図で赤で囲んだ部分画像とカーネルの画素単位の積の和をとると 65 - 20 となり X 方向の変化量を調べることができていることがわかりますね。このカーネルが微分フィルタの X 方向のカーネルです。

ただしこの方法には問題があって、65 - 20 の計算結果は注目画素に対する変化点というよりは 65 と 20 のある画素の中間の変化量を表していることになってしまいます。そこで以下のように処理する場合が多いです。

画像3

注目画素の両隣りの画素の変化量を調べます。この場合はどのようなカーネルを用意すればよいでしょうか。

画像4

これで注目画素における変化点が求まったことになりますね。ではコードと一緒に見ていきましょう。原画像は Lena です。

画像5

import cv2
import numpy as np

filebase = 'lena'
path = filebase + '.tiff'
image = cv2.imread(path, 1)
gray_image = cv2.cvtColor(image, cv2.COLOR_RGB2GRAY)

kernel_x = np.array([[0, -1, 0],
                    [0,  0, 0],
                    [0,  1, 0]])
kernel_y = np.array([[ 0,  0, 0],
                    [-1,  0, 1],
                    [ 0,  0, 0]])

diff_x = cv2.filter2D(gray_image, cv2.CV_64F, kernel_x)
diff_y = cv2.filter2D(gray_image, cv2.CV_64F, kernel_y)

cv2.imshow('diff_x', diff_x)
cv2.imshow('diff_y', diff_y)

cv2.waitKey(0)
cv2.destroyAllWindows()

読み込んだ画像をグレイスケールに変換し、X方向のカーネルと Y方向のカーネルでそれぞれ微分フィルタで処理した結果が別ウィンドウで表示されます。以下、X方向、Y方向の順です。

画像6

画像7

今回は空間フィルターと周辺の用語を交えて最も基本的なエッジ抽出フィルタである微分フィルタについてまとめました。

OpenCV 空間フィルタに関するまとめの続きは以下からどうぞ。

では、ごきげんよう。


この記事が気に入ったらサポートをしてみませんか?