OpenCVのsubtractについての小ネタ
Posted On 2019-10-05
OpenCVのsubtractと通常のNumpyの引き算の差が気になったのでメモ。実際に試してみました。
環境:Numpy:1.16.3, OpenCV:4.1.0
目次
NumpyとOpenCVのsubtractの差
OpenCVとNumpy配列は密接に関係していて、新しい画像を作るときにnp.zerosなどのNumpy関数で初期化します。
ありがちなのがuint8型で初期化して、OpenCVで画像として扱うパターンです。uint8のNumpy配列を画像と見たてみます。普通にNumpyで引くケースと、OpenCVのsubtractで引くケースを比較します。
import cv2
import numpy as np
x = np.arange(27, dtype=np.uint8).reshape(3, 3, 3)
y = np.arange(27, dtype=np.uint8)[::-1].reshape(3, 3, 3)
print(x - y) # 普通に引き算
print(cv2.subtract(x, y)) # OpenCVのsubtract
# Numpyの引き算
[[[230 232 234]
[236 238 240]
[242 244 246]]
[[248 250 252]
[254 0 2]
[ 4 6 8]]
[[ 10 12 14]
[ 16 18 20]
[ 22 24 26]]]
# OpenCVのsubtract
[[[ 0 0 0]
[ 0 0 0]
[ 0 0 0]]
[[ 0 0 0]
[ 0 0 2]
[ 4 6 8]]
[[10 12 14]
[16 18 20]
[22 24 26]]]
Numpyの引き算はオーバーフローしているのに、OpenCVの引き算は0で底打ちされていてオーバーフローしていません。
uint8以外ならどうか?
OpenCVのsubtractはただ単にマイナスの値を0と決め打ちしている疑惑が否定できないので、uint8からint32に変更して計算してみます。
x = np.arange(27, dtype=np.int32).reshape(3, 3, 3)
y = np.arange(27, dtype=np.int32)[::-1].reshape(3, 3, 3)
print(x - y)
print(cv2.subtract(x, y))
# Numpyの引き算
[[[-26 -24 -22]
[-20 -18 -16]
[-14 -12 -10]]
[[ -8 -6 -4]
[ -2 0 2]
[ 4 6 8]]
[[ 10 12 14]
[ 16 18 20]
[ 22 24 26]]]
# OpenCVのsubtract
[[[-26 -24 -22]
[-20 -18 -16]
[-14 -12 -10]]
[[ -8 -6 -4]
[ -2 0 2]
[ 4 6 8]]
[[ 10 12 14]
[ 16 18 20]
[ 22 24 26]]]
結果は同じになりました。つまり、OpenCVのsubtractはマイナスの値を0に丸めておらず、型に応じてオーバーフロー起こさないように調整しているだけのようです。
まとめ
OpenCVのsubtractとNumpyの引き算の差は、オーバーフローを引き起こすかどうか
Shikoan's ML Blogの中の人が運営しているサークル「じゅ~しぃ~すくりぷと」の本のご案内
技術書コーナー
北海道の駅巡りコーナー