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