超音波センサーで、近くに来た物体だけを撮影してみました
1 はじめに
CX事業本部の平内(SIN)です。
今回、超音波センサーとWebカメラを組み合わせて、近くに物体がある時だけ、撮影する仕組みを作ってみました。
「カメラの前に商品をかざしたタイミングで、商品を推論したい」というのが、最終的な目的です。
最初に、動作している様子です。
超音波センサーは、Webカメラの画角と同じ方向で、雑にくっつけました。センサー値の取得とWebカメラの制御は、RaspberryPiで処理されています。
なお、RaspberryPiでHC-SR04を使用する方法が、下記で詳しく解説されています。
今回は、こちらを参考に作業させて頂きました。
参考:RaspberryPiで超音波を使った距離測定
2 超音波センサーモジュール HC-SR04
使用したセンサーモジュールは、HC-SR04です。
以下は、ブレッドボードで動作確認している様子です。
↑ RasPI側の2番は、「5V」の誤りです。
参考:https://www.instructables.com/Simple-Arduino-and-HC-SR04-Example/
3 接続
Webカメラとセンサーは、マスキングテープで雑に巻いただけです。
Echo PINとGPIOの接続にだけ、制限抵抗が入っています。
4 コード
コードは、以下のとおりです。 超音波センサーで常に距離を測定し、30cm以内を検出すると撮影開始となります。また、30cm以上のフレームが5回連続すると撮影は終了します。
# -*- coding: utf-8 -*- import cv2 import time import RPi.GPIO as GPIO import smbus import numpy as np # Webカメラ DEVICE_ID = 0 WIDTH = 800 HEIGHT = 600 FPS = 24 # 超音波センサー(HC-SR04) GPIO.setwarnings(False) GPIO.setmode(GPIO.BCM) GPIO.setup(17,GPIO.OUT) # Trig GPIO.setup(27,GPIO.IN) # Echo def getDistance(): GPIO.output(17, GPIO.LOW) GPIO.output(17, True) time.sleep(0.00001) GPIO.output(17, False) while GPIO.input(27) == 0: signaloff = time.time() while GPIO.input(27) == 1: signalon = time.time() timepassed = signalon - signaloff return timepassed * (331.50 + 0.606681)* 100/2 def main(): cap = cv2.VideoCapture (DEVICE_ID) # フォーマット・解像度・FPSの設定 cap.set(cv2.CAP_PROP_FRAME_WIDTH, WIDTH) cap.set(cv2.CAP_PROP_FRAME_HEIGHT, HEIGHT) cap.set(cv2.CAP_PROP_FPS, FPS) # フォーマット・解像度・FPSの取得 width = cap.get(cv2.CAP_PROP_FRAME_WIDTH) height = cap.get(cv2.CAP_PROP_FRAME_HEIGHT) fps = cap.get(cv2.CAP_PROP_FPS) print("fps:{} width:{} height:{}".format(fps, width, height)) rec = False count = 0 while True: # 距離の測定 distance = getDistance() print("{:.1f} cm rec:{}".format(distance, rec)) if(rec == False): # 30cm以内を検出した場合に録画開始 if(distance < 30): rec = True count = 0 else: # 30cm以上の場合、カウント if(distance < 30): count = 0 else: count += 1 # 30cm以上のフレームが5を超えたら、録画終了 if(count > 5): rec = False # ダミーの画像(ブラック) frame = np.zeros((int(height), int(width), 3)) # 録画中の場合、カメラ画像を取得する if(rec): # カメラ画像取得 _, frame = cap.read() if(frame is None): continue # 画像表示 cv2.imshow('frame', frame) if cv2.waitKey(1) & 0xFF == ord('q'): break # オブジェクト破棄 cap.release() cv2.destroyAllWindows() GPIO.cleanup() if __name__ == '__main__': main()
5 最後に
今回は、一定の距離に物体が来た時だけ撮影する仕組みを試してみました。 予想以上に動きが良いので、本来の目的である下記にも充分利用できるような気がしてきました。
「カメラの前に商品をかざしたタイミングで、商品を推論したい」