水槽の静止画/動画撮影
https://scrapbox.io/files/6182027aec7797001d550ba9.png
Raspberry Piにカメラモジュールを取り付けて水槽内の様子を撮影(静止画/動画)する
撮影対象が水槽であるだけなので、もちろん他の用途にも転用できる
注意
このページの内容はRaspberry Pi OSBuster32bit版を想定したものとなる
Busterの次のバージョンであるBullseyeでは撮影に使うコマンド群が刷新されている
64bit版ではraspistill等の撮影コマンドがサポートされていなかった
要件
水槽内を撮影した静止画データを取得できる
水槽内を撮影した動画データを取得できる
Twitter経由で水槽内の静止画/動画を確認できる
仕様
仕様1:Raspberry Piからプログラムを実行すると、現在の水槽内を撮影した静止画データが保存される
仕様2:Raspberry Piからプログラムを実行すると、現在の水槽内を撮影した動画データが保存される
仕様3:TwitterBotにコマンドを送ると、水槽内の静止画/動画がリプライされる
使用したもの
あしゅりーアクアリウムの場合
table:使用したもの
ラズパイ Raspberry Pi 4 ModelB 4GB
カメラモジュール OV5647
カメラモジュール:OV5647
ラズパイとCSI-2で接続できれば何でもOK
もちろんUSB接続のカメラでもいいけどせっかくラズパイ使ってるからね!
今回使ったやつ(自立できるタイプ)
https://scrapbox.io/files/621979745a2d160023880950.jpg
特にこだわりは無い
設計
流れは以下の通り
カメラモジュールの取り付け
静止画撮影プログラムを作成
動画撮影プログラムを作成
TwitterBotのコマンド応答で静止画/動画を返せるようにする
カメラモジュールの取り付け
ラズパイの電源をオフにする(壊れるので)
以下を参考にカメラモジュールをRaspberry Piに取り付ける
ラズパイの電源を入れ、以下によりカメラ機能を有効化する
$ sudo raspi-config
Interface OptionsにてCameraを有効化する
$ sudo rebootでラズパイを再起動
$ vcgencmd get_cameraにてsupported=1 detected=1と返ってくればカメラが認識されている
水槽内をいい感じに撮影できる位置にカメラを設置する
あしゅりー.iconあしゅりーアクアリウムの場合
https://scrapbox.io/files/62198d5594cbf0001d3e84f0.jpg
発泡スチロール工作おじさんと化してしまった
静止画撮影プログラムを作成
まずは静止画撮影コマンドを実行して撮影できるか確認する
code:Terminal
$ raspistill -o output.jpg
output.jpgにて静止画データを確認できればOK
raspistillコマンドの各種オプション(サイズや画質など)については必要に応じて適宜チューニングのこと
次にこれをpythonで実行できるようにする
code:camera.py
import subprocess
def photo():
# 静止画データ出力先パス
path_photo = '/home/asyley/output.jpg'
cmd = 'raspistill -o '
cmd += path_photo
res = subprocess.run(cmd, shell=True)
if res.returncode != 0:
# 撮影失敗
return 'error'
return path_photo
if __name__ == '__main__':
photo()
静止画データ出力先パスpath_photoは適宜置き換えること
上記を実行する
code:Terminal
$ python3 camera.py
path_photoに静止画データが出力されていればOK
完了 ⇒ 仕様1:Raspberry Piからプログラムを実行すると、現在の水槽内を撮影した静止画データが保存される
動画撮影プログラムを作成
まずは動画撮影コマンドを実行して撮影できるか確認する
code:Terminal
$ raspivid -o output.h264
output.h264にて動画データ(デフォルト5秒間の動画)を確認できればOK
raspividコマンドの各種オプション(秒数やサイズ、画質など)については必要に応じて適宜チューニングのこと
上記の通りraspividの出力形式はh264であるため、後で扱いやすいようにMP4Boxにてmp4に変換する処理も加える
code:Terminal
$ sudo apt install gpac
$ MP4Box -add output.h264 output.mp4
output.mp4にて変換された動画を確認できればOK
次にこれをpythonで実行できるようにする
code:camera.py
import subprocess
def video():
# 動画データ出力先パス
path_video_h264 = '/home/asyley/output.h264'
path_video_mp4 = '/home/asyley/output.mp4'
cmd = 'raspivid -o '
cmd += path_video_h264
res = subprocess.run(cmd, shell=True)
if res.returncode != 0:
# 撮影失敗
return 'error'
# h264をmp4に変換
cmd = 'MP4Box -add '
cmd += path_video_h264 + ' '
cmd += path_video_mp4 + ' '
cmd += '-new'
subprocess.run(cmd, shell=True)
return path_video_mp4
if __name__ == '__main__':
video()
動画データ出力先パスpath_video_h264 path_video_mp4はそれぞれ適宜置き換えること
上記を実行する
code:Terminal
$ python3 camera.py
path_video_mp4に動画データが出力されていればOK
完了 ⇒ 仕様2:Raspberry Piからプログラムを実行すると、現在の水槽内を撮影した動画データが保存される
ここまででシステム構成図内「Camera」が実現できたことになる
システム構成図
システム構成図.icon
TwitterBotのコマンド応答で静止画/動画を返せるようにする
これより先は以下が実現できていることを前提とする
システム構成図内「Twitter API」
TwitterBotにオレオレコマンドを追加する
table:「photo」コマンド
形式 @xxx photo
応答 コマンド受信時の最新の静止画
@Asyley_aqua photoというメンションに反応し、その時の水槽内を撮影して画像をリプライするようにMyStreamListenerクラスのon_status()に以下を追加する
code:tweet_listener.py
import re
import camera
class MyStreamListener(tweepy.StreamListener):
def on_status(self, status):
if re.match(r'@Asyley_aqua photo.*', status.text):
# 静止画の撮影
path = camera.photo()
if path == 'error':
pass # 撮影失敗時の処理
else:
reply_text = '@' + status.user.screen_name
api.update_with_media(status=reply_text, in_reply_to_status_id=status.id, filename=path)
ここでphoto()の実行結果としては異常時はerror、正常時は静止画データのファイルパスが得られる
正常時はこのパスが格納されたpathをupdate_with_media()のfilenameに指定することでTwitterBotが返信する際に静止画データを添付できる
次に動画についても対応する
table:「video」コマンド
形式 @xxx video
応答 コマンド受信時の最新の動画
基本的な流れは静止画と同じであるがここまで使ってきたtweepyのライブラリでは簡単に動画投稿できる方法が無い
そのため代替として一番簡単なpython-twitterを使う方法で実現する
code:Terminal
$ pip install python-twitter
tweepyと同様に最初に認証を通しておき、動画アップロードとその動画付きツイートの投稿の際に使用する
code:tweet_listener.py
import re
import camera
import twitter
# python-twitterの認証
api_twitter = twitter.Api( consumer_key='xxxxxx',
consumer_secret='xxxxxx',
access_token_key='xxxxxx',
access_token_secret='xxxxxx' )
class MyStreamListener(tweepy.StreamListener):
def on_status(self, status):
if re.match(r'@Asyley_aqua video.*', status.text):
# 動画の撮影
path = camera.video()
if path == 'error':
pass # 撮影失敗時の処理
else:
reply_text = '@' + status.user.screen_name
mediaId = api_twitter.UploadMediaChunked(media=path, media_category="tweet_video")
time.sleep(10) # アップロード完了まで時間がかかるので待つ
api_twitter.PostUpdate(status=reply_text, in_reply_to_status_id=status.id,media=mediaId)
これによりphotoコマンド、およびvideoコマンドで静止画/動画をTwitterBotの返信から取得できる
完了 ⇒ 仕様3:TwitterBotにコマンドを送ると、水槽内の静止画/動画がリプライされる
活用
出先から自宅水槽の様子を確認したりが主な用途となるが、
もっと快適性を求めるならば水槽のライブ配信を行い、かつ外部のネットワークから視聴できる環境を構築すると良い