【OpenCV-Python】filter2D(任意カーネルフィルタ)

OpenCVで任意のカーネルを指定してフィルタ処理を行うには、filter2D()関数を用います。

カーネルそのものは、numpyの二次元配列で指定します。

 

構文

filter2D( src, ddepth, kernel[, dst[, anchor[, delta[, borderType]]]] ) -> dst

引数

src 処理を行う画像データを指定します。
ddepth 出力データの1画素1chあたりのビット深度を指定します。
-1 を指定すると、入力データと同じビット深度になります。
設定できる組み合わせは下記を参照ください。
kernel kernelの値を二次元配列で指定します。
カラーなどの複数チャンネルのデータでは、すべて同じカーネルが適用されます。
anchor kernelの基準位置を指定します。
anchorを指定しないか、(-1, -1)を指定すると、基準位置はカーネルの中心位置となります。
delta kernelで処理された後にdeltaの値が加えられます。
borderType ボーダー処理の種類をBorderTypesのenumで指定します。

ddepthに指定可能な組み合わせ

入力データのビット深度 出力データのビット深度
cv2.CV_8U -1, cv2.CV_16S, cv2.CV_32F, cv2.CV_64F
cv2.CV_16U, cv2.CV_16S -1, cv2.CV_16S, cv2.CV_32F, cv2.CV_64F
cv2.CV_32F -1, cv2.CV_32F
cv2.CV64F -1, cv2.CV_64F


戻り値

dst フィルタ処理された画像データ
ビット深度はddpethで指定された値になります。

サンプルプログラム

カーネルの値を自分で指定したガウシアンフィルタ処理を行うサンプルプログラムを以下に示します。

import cv2
import numpy as np

# 処理前画像の読込
src = cv2.imread("Mandrill.bmp", cv2.IMREAD_UNCHANGED)

# 3x3のガウシアンフィルタのカーネル
kernel = np.array([
    [1, 2, 1],
    [2, 4, 2],
    [1, 2, 1]
    ], dtype = np.float32)
kernel /= 16

# 任意カーネルフィルタの実施
dst = cv2.filter2D(src, -1, kernel)

# 任意カーネルフィルタ処理後の画像表示
cv2.imshow("Src Image", src )
cv2.imshow("filter2D", dst)
cv2.waitKey()

実行結果

 

出力先のビット深度に符号なしの値を指定すると、kernelにより計算された値がビット深度の範囲を超える場合、値はクリップされます。

例えば、出力先のビット数が8bitのとき、ビット深度の範囲は0~255なので、計算結果が負の場合は0に、255を超える場合は255に補正されます。

 

評価プログラム

import cv2
import numpy as np

src = np.array([
    [0, 0, 0, 255, 255, 255, 0, 0, 0],
    [0, 0, 0, 255, 255, 255, 0, 0, 0],
    [0, 0, 0, 255, 255, 255, 0, 0, 0],
    [0, 0, 0, 255, 255, 255, 0, 0, 0],
    [0, 0, 0, 255, 255, 255, 0, 0, 0],
    [0, 0, 0, 255, 255, 255, 0, 0, 0],
    [0, 0, 0, 255, 255, 255, 0, 0, 0],
    [0, 0, 0, 255, 255, 255, 0, 0, 0],
    [0, 0, 0, 255, 255, 255, 0, 0, 0]
    ], dtype = np.uint8)

# ソーベルフィルタのカーネル
kernel = np.array([
    [-1, 0, 1],
    [-2, 0, 2],
    [-1, 0, 1]
    ])

# 任意カーネルフィルタ
dst = cv2.filter2D(src, -1, kernel)

print("-----src------------------------------")
print(src)
print("-----dst------------------------------")
print(dst)

実行結果

—–src——————————
[[ 0 0 0 255 255 255 0 0 0]
[ 0 0 0 255 255 255 0 0 0]
[ 0 0 0 255 255 255 0 0 0]
[ 0 0 0 255 255 255 0 0 0]
[ 0 0 0 255 255 255 0 0 0]
[ 0 0 0 255 255 255 0 0 0]
[ 0 0 0 255 255 255 0 0 0]
[ 0 0 0 255 255 255 0 0 0]
[ 0 0 0 255 255 255 0 0 0]]
—–dst——————————
[[ 0 0 255 255 0 0 0 0 0]
[ 0 0 255 255 0 0 0 0 0]
[ 0 0 255 255 0 0 0 0 0]
[ 0 0 255 255 0 0 0 0 0]
[ 0 0 255 255 0 0 0 0 0]
[ 0 0 255 255 0 0 0 0 0]
[ 0 0 255 255 0 0 0 0 0]
[ 0 0 255 255 0 0 0 0 0]
[ 0 0 255 255 0 0 0 0 0]]

 

出力先のビット深度を符号ありの16bitにしたときのサンプルは以下の通りです。

import cv2
import numpy as np

src = np.array([
    [0, 0, 0, 255, 255, 255, 0, 0, 0],
    [0, 0, 0, 255, 255, 255, 0, 0, 0],
    [0, 0, 0, 255, 255, 255, 0, 0, 0],
    [0, 0, 0, 255, 255, 255, 0, 0, 0],
    [0, 0, 0, 255, 255, 255, 0, 0, 0],
    [0, 0, 0, 255, 255, 255, 0, 0, 0],
    [0, 0, 0, 255, 255, 255, 0, 0, 0],
    [0, 0, 0, 255, 255, 255, 0, 0, 0],
    [0, 0, 0, 255, 255, 255, 0, 0, 0]
    ], dtype = np.uint8)

# ソーベルフィルタのカーネル
kernel = np.array([
    [-1, 0, 1],
    [-2, 0, 2],
    [-1, 0, 1]
    ])

# 任意カーネルフィルタ
dst = cv2.filter2D(src, cv2.CV_16S, kernel)

print("-----src------------------------------")
print(src)
print("-----dst------------------------------")
print(dst)

実行結果

—–src——————————
[[ 0 0 0 255 255 255 0 0 0]
[ 0 0 0 255 255 255 0 0 0]
[ 0 0 0 255 255 255 0 0 0]
[ 0 0 0 255 255 255 0 0 0]
[ 0 0 0 255 255 255 0 0 0]
[ 0 0 0 255 255 255 0 0 0]
[ 0 0 0 255 255 255 0 0 0]
[ 0 0 0 255 255 255 0 0 0]
[ 0 0 0 255 255 255 0 0 0]]
—–dst——————————
[[ 0 0 1020 1020 0 -1020 -1020 0 0]
[ 0 0 1020 1020 0 -1020 -1020 0 0]
[ 0 0 1020 1020 0 -1020 -1020 0 0]
[ 0 0 1020 1020 0 -1020 -1020 0 0]
[ 0 0 1020 1020 0 -1020 -1020 0 0]
[ 0 0 1020 1020 0 -1020 -1020 0 0]
[ 0 0 1020 1020 0 -1020 -1020 0 0]
[ 0 0 1020 1020 0 -1020 -1020 0 0]
[ 0 0 1020 1020 0 -1020 -1020 0 0]]

 

参照ページ

https://docs.opencv.org/4.8.0/d4/d86/group__imgproc__filter.html#ga27c049795ce870216ddfb366086b5a04

https://docs.opencv.org/4.8.0/d4/d86/group__imgproc__filter.html#filter_depths

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です

このサイトはスパムを低減するために Akismet を使っています。コメントデータの処理方法の詳細はこちらをご覧ください