【Python/OpenCV】微分フィルタの注意点(負の値の処理)

この記事では、Python版OpenCVの微分フィルタ(Sobelなど)を利用する時の注意点についてソースコード付きで解説します。

微分フィルタの注意点(負の値の処理)

微分フィルタで画像の勾配を計算すると、黒(0)→白(255)へ変化するときの微分値は正、その逆は負になります。
OpenCVの微分フィルタの関数(cv2.Sobelやfilter2Dなど)では、デフォルトのデータ型(8ビット符号なし整数)で使用すると0負の値は0になります。
つまり、負の勾配(白→黒)の情報を失ってしまいます。

負の勾配情報を残すには、データ型をfloat64(cv2.CV_64F)などに指定してやります。

実際にコードと実行結果を見てみましょう。

サンプルコード(OpenCV)

実行結果

10*10の入力画像で試しています。

dst1=
 [[  0   0   0   0   0   0   0   0   0   0]
 [  0   0   0   0   0   0   0   0   0   0]
 [  0   0   0   0   0   0   0   0   0   0]
 [  0   0 255 255   0   0   0   0   0   0]
 [  0   0 255 255   0   0   0   0   0   0]
 [  0   0 255 255   0   0   0   0   0   0]
 [  0   0 255 255   0   0   0   0   0   0]
 [  0   0   0   0   0   0   0   0   0   0]
 [  0   0   0   0   0   0   0   0   0   0]
 [  0   0   0   0   0   0   0   0   0   0]]

dst2=
 [[   0.    0.    0.    0.    0.    0.    0.    0.    0.    0.]
 [   0.    0.    0.    0.    0.    0.    0.    0.    0.    0.]
 [   0.    0.    0.    0.    0.    0.    0.    0.    0.    0.]
 [   0.    0.  255.  255.    0.    0.    0. -255. -255.    0.]
 [   0.    0.  255.  255.    0.    0.    0. -255. -255.    0.]
 [   0.    0.  255.  255.    0.    0.    0. -255. -255.    0.]
 [   0.    0.  255.  255.    0.    0.    0. -255. -255.    0.]
 [   0.    0.    0.    0.    0.    0.    0.    0.    0.    0.]
 [   0.    0.    0.    0.    0.    0.    0.    0.    0.    0.]
 [   0.    0.    0.    0.    0.    0.    0.    0.    0.    0.]]

配列のデータ型をfloat64にすると、負の値が残っていることがわかります。
画像で見やると次のようになりまう。

■10*10の入力画像(左)、負の値が0になった出力画像(中)、負の値を正にした出力画像(右)

ポイント

float64で微分画像の配列を取り出した後、

np.uint8(np.abs(dst2))

で配列内の要素の絶対値を計算します。
これにより、負の値は正に変換されます。(例:-255 → +255)
そして、データ型を符号なし8ビット整数に戻してからcv2.imwrite()で画像を出力することで白→黒の勾配も出力画像に反映できます。

サンプルコード(NumPy)

NumPyで実装した場合は、データ型は畳み込み演算の計算過程で自動的にfloat64に変換されます。
そのため、先程のポイント

np.uint8(np.abs(dst2))

だけ実装すれば出力画像に負の勾配を反映させることが出来ます。

【おすすめ記事】
PythonでOpenCV入門 サンプル集
【Python】画像処理プログラミング入門
【画像処理入門】アルゴリズム&プログラミング

シェア&フォローお願いします!