はじめに
物体の検出方法でよく使われるのは、差分をとってRGBの差分を取ることですが、
検出したい物体の性質を考えることにより、もっと適した検出方法があります。
対象
私は今、最終的にダイスの出目を判別できるようなシステムを作ろうとしています。
ダイスの性質としては次のようなものが考えられます。
- 室内で使用する
- 小さい
- 様々な色がある
背景からダイスだけ切り出そうとした場合、
ダイスの影が物体検出の邪魔になることがあります。
今回はRGBではなく、HSVで物体検出することによって影の影響を抑えてみます。
影となる場所は彩度・輝度の変動は小さく、色相の変化はないはずですので、それを踏まえたしきい値の選択をしています。
なお、HSVへの変換方法はOpenCVとVisual C++による画像処理と認識(4)を、
HSVの各チャンネルごとの変換にはNumPy配列ndarrayを分割を参考にしました。
最後のマスク処理はPython + OpenCVによるマスク画像適用方法を参考にしています。
import cv2
import numpy as np
GAUSSIAN_SIZE = (7,7)
camera = cv2.VideoCapture(0)
# 背景画像とダイスの画像を取得
result, image_base = camera.read()
if not result:
exit()
image_base_blured = cv2.GaussianBlur(image_base, GAUSSIAN_SIZE, 0)
cv2.imshow("baseImage",image_base)
cv2.waitKey(0)
# カメラの画像を読み取るとき、前回のカメラのバッファを読んでる?
result, image_dice = camera.read()
result, image_dice = camera.read()
if not result:
exit()
image_dice_blured = cv2.GaussianBlur(image_dice, GAUSSIAN_SIZE, 0)
# HSVに変換した上で差分をとる
base_hsv = cv2.cvtColor(image_base_blured, cv2.COLOR_RGB2HSV)
dice_hsv = cv2.cvtColor(image_dice_blured, cv2.COLOR_RGB2HSV)
diff_hsv = cv2.absdiff(base_hsv, dice_hsv)
# 2次元目を3つに分割→HSVの差分のチャンネルを分離
diff_imagelist = np.split(diff_hsv,3,2)
width = diff_hsv.shape[0]
height = diff_hsv.shape[1]
hdiff = diff_imagelist[0].reshape(width,height)
sdiff = diff_imagelist[1].reshape(width,height)
vdiff = diff_imagelist[2].reshape(width,height)
image_dice[hdiff>15] = [255,0,0]
image_dice[sdiff>50] = [0,255,0]
image_dice[vdiff>65] = [0,0,255]
cv2.imshow("diceImage",image_dice)
cv2.waitKey(0)
cv2.destroyAllWindows()
結果
結論
画像処理を行いたい対象がいる場合、対象物に適した処理方法がないか考えると、処理が楽になることがあります。
今回はダイスに適した処理を行うことができました。