Edited at

物体・条件を考慮した物体検出


はじめに

物体の検出方法でよく使われるのは、差分をとって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()


結果

dice.png

ダイスの例

dice_hsv.png

上記コードで分割した例

dice_rgb.png

RGBでしきい値をとった場合


結論

画像処理を行いたい対象がいる場合、対象物に適した処理方法がないか考えると、処理が楽になることがあります。

今回はダイスに適した処理を行うことができました。