この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。
1 はじめに
CX事業本部の平内(SIN)です。
店舗の商品監視をターゲットに、OpenCVを利用した撮影について、数日前から試してきました。
[OpenCV] ArUcoマーカーを使用して、安定した商品の監視映像を撮影してみました。
[OpenCV] 一定期間動かないものだけを撮影する
今回は、上記の簡単な拡張として、ArUcoマーカーで売り切れ商品の検出を試してみました。
最初に、動作しているようすです。
左の画面が、Webカメラで撮影した映像そのままで、右の画面が、その一部を監視している画面です。 監視の画面では、緑の枠で商品の位置を認識しており、全部無くなってしまうと、棚に貼ってある「近日入荷予定シール」に着いているマーカーを検出し、赤枠表示にしています。
2 近日入荷予定
商品が全てなくなった時見えるように、「近日入荷予定シール」が張っています。これは、マーカーを一緒に印刷して、貼っているだけです。
このマーカーは、id=0であり、各商品の上に配置しているマーカーや、四隅の基準となるマーカーとは、idが異なりますが、「近日入荷予定シール」は、いづれの商品でも同じです。
下図のように、各商品のマーカー位置を基準に、商品が有るべき位置を計算して(細線の緑枠)、その中にid=0のマーカーが存在するかどうかで、売り切れの判定(太線の)が行われます。
3 コード
監視エリア内で、商品の位置を計算し、「近日入荷予定シール」を検出しているコードは、以下の通りです。
# 品切れの検知
def confirmSoldOut(frame, dictionary):
# マーカーから商品まで距離
margin = 50
# 一つの商品のサイズ
width = 300
height = 420
# 描画領域の座標系でマーカーを取得する
corners, ids, rejectedImgPoints = aruco.detectMarkers(frame, dictionary)
# index=15,16,17のマーカーを検出する
for index in [15,16,17]:
# マーカーの中心を取得
marker = getMarkerMean(ids, corners, index)
if(marker!=None):
# マーカーの中心座標から商品のエリアを算出する
x = marker[0]
y = marker[1]
x1 = int(x-(width/2))
y1 = int(y+margin)
x2 = int(x+(width/2))
y2 = int(y+height+margin)
# 商品エリアの中に、index=0(売り切れ)マーカーが存在するかどうか確認
isSoldOut = False
for (i,id) in enumerate(ids):
if(id[0]==0):
v = np.mean(corners[i][0],axis=0)
if(x1 < v[0] and v[0] < x2 and y1 < v[1] and v[1] < y2):
isSoldOut = True
# 売り切れの場合に、赤枠を表示する
if(isSoldOut):
frame = cv2.rectangle(frame, (x1, y1), (x2, y2),(0,0,255),5)
else:
frame = cv2.rectangle(frame, (x1, y1), (x2, y2),(0,255,0),1)
return frame
上記以外については、先のブログと同じなので、ここでは、省略させて下さい。
参考:[OpenCV] ArUcoマーカーを使用して、安定した商品の監視映像を撮影してみました。
4 最後に
今回は、「近日入荷予定シール」を検出しても、赤枠を表示しているだけですが、これをトリガーに、スタッフへの通知や、在庫調整に繋げることも可能かもしれません。