定点観察装置をラズパイで作る(装置の構成)

技術ネタ

USBカメラを使って何らかの変化を捉えるための装置をラズパイで作ります。

装置を実際に作るにあたって直面した問題についても解説したいと思います。

装置を使って梅酒の変化を捉えたのでこちらもご覧ください。

梅酒が熟成する様子を観察するためのガチ装置をラズパイで作った

スポンサーリンク

定点観察における注意

ここでの注意は画像の色の変化を捉えるなど、厳密に撮影条件をそろえる必要がある場合の注意です。

単に動きの変化を捉えるだけであればここの注意は必要ないかもしれません。

照明条件

照明は撮影される画像に大きく影響を与えます。

明るさの統一はもちろん、太陽光などの外光が入らないようにする必要があります。

※照明の明るさも一定ではない可能性もあります。厳密に照度を一定に保ちたい場合はLEDに入る電流を一定に保つための装置が付いた照明を使用する必要があります。

撮影環境や照明の色

人間は白い物体を白と脳で自動的に認識することができ、大体どんな照明環境下でも白いものは白いと認識することが出来ます。しかしカメラはそれができません。そのため、青白い照明環境下では青白っぽい色味の写真ができてしまうなど、人間の見た目通りに撮影できないことがあります。(そのためにホワイトバランスを自動調整する機能がカメラに備わっています。)

撮影環境の色や照明の色はカメラで被写体を撮影する際映りこんでくる可能性があるため、撮影環境や照明の色は白系であることが理想だと思います。(厳密にどのような色を使うべきかは筆者は把握していないため、各自調査してください。)

カメラパラメータ

USBカメラはきれいに撮影するための様々なカメラパラメータが自動で設定されています(ホワイトバランスや露出時間など)。

しかしこのパラメータは大体の場合、撮影するごとに自動的に調整されるもののため、異なる撮影間で同じパラメータが使用されていない可能性があります。そのため、条件を統一したい場合はカメラパラメータは固定する必要があります。

スポンサーリンク

定点観察の流れ

定点観察は以下の流れで行います。

  1. LEDを点灯
  2. fswebcamでカメラパラメータを設定して撮影
  3. LEDを消灯
  4. rcloneで撮影した画像をGoogle Driveに保存

これをcronで一時間ごとに実行します。また、エラーが起きた時のためにline notifyで通知を送る都合、上記コマンドをpython上で実行します。

rcloneでのバックアップ方法についてはこちらで解説しています。

LED

今回使用したLEDはamazonで2 mで1200円くらいのLEDテープを使用しました。電源はUSB供給です。

安物のため、出力が安定しているかはわかりません。

hub-ctrl

LEDは撮影時のみ点灯させるため、USBの電源供給を制御します。

RaspberryPiのUSBポートの電源On/Offを制御する

こちらを参考にhub-ctrlをインストールしました。

USBカメラ

USBカメラはLogicoolのc270というものを使用しました。

fswebcam

カメラの制御はfswebcamというパッケージを利用します。

カメラの撮影はOpenCVでもできるのですが、カメラパラメータを固定する方法がOpenCVでは見つからなかったためこちらを採用しました。fswebcamの使用方法は下記を参考にしました。

ラズパイ+ウェブカメラC200で静止画を撮影してみる

今回は下記のコマンドでパラメータを固定して撮影を行いました。

fswebcam --delay=3 --skip=20 --no-banner --set=gain=10 --set=brightness=55% --set=contrast=36 --set "White Balance Temperature, Auto"=False --set "White Balance Temperature"=4000 --rotate 270 --set=sharpness=20 --png 0 -v -r 640x480 [path]
スポンサーリンク

プログラム

from datetime import datetime
import subprocess
import time
import requests

# line notify token
LINE_NOTIFY_TOKEN = 'token' # line notifyでトークンを取得する必要があります。
def send_message(message, filepath=None):
    headers = {'Authorization' : 'Bearer '+ LINE_NOTIFY_TOKEN}
    payload = {'message':  message}
    if filepath is not None:
        files = {'imageFile': open(filepath, 'rb')}
        res = requests.post('https://notify-api.line.me/api/notify', headers=headers, params=payload, files=files)
    else:
        res = requests.post('https://notify-api.line.me/api/notify', headers=headers, params=payload)
    print(res.json())

# commands
command_light_on = 'sudo hub-ctrl -b 1 -d 2 -P 2 -p 1'
command_light_off = 'sudo hub-ctrl -b 1 -d 2 -P 2 -p 0'
command_capture = 'fswebcam --delay=3 --skip=20 --no-banner --set=gain=10 --set=brightness=55% --set=contrast=36 --set "White Balance Temperature, Auto"=False --set "White Balance Temperature"=4000 --rotate 270 --set=sharpness=20 --png 0 -v -r 640x480 [path]'
command_backup = 'sudo rclone copy [path] camera:/camera'

# USB light ON
try:
    res = subprocess.run(command_light_on, shell=True)
    print('Light on.')
except:
    send_message('error at light on.')
    raise 'Light on error.'

time.sleep(5) # wait for camera activation
# Camera capture
print('Start camera capture.')
date = datetime.now().strftime('%Y%m%d_%H%M%S')
path = '/home/pi/camera/img/{}.png'.format(date)
try:
    command_capture = command_capture.replace('[path]', path)
    res = subprocess.run(command_capture, shell=True)
    print('Image captured.')
except:
    send_message('error at image capture.')
    raise 'Capture error.'

# USB light ON
try:
    res = subprocess.run(command_light_off, shell=True)
    print('Light off.')
except:
    send_message('error at light off.')
    raise 'Light off error.'

# backup to drive
try:
    command_backup = command_backup.replace('[path]', path)
    res = subprocess.run(command_backup, shell=True)
    print('Backuped image to drive.')
except:
    send_message('error at backup.')
    raise 'Backup error.'

# send image
now = datetime.now()
if now.hour==7: # 毎朝7時の撮影でline通知
    send_message(now.strftime('%m/%d') + ' 本日の梅酒の様子', filepath=path)

print('End auto_capture.py.')

実行上の注意

USB電源供給はプログラム実行前はOFFとなっているため、ONにした直後はカメラなどが認識されていません。そのため、ONにしてから数秒待ってからカメラの制御を行う必要があります。

コメント

タイトルとURLをコピーしました