ラズパイ+Webカメラで定点観察を行う


植物を育てているのですが、定点観察して、植物の育成状況を見たいと思いました。
定点観察の画像の撮り方から、便利なTipsを紹介します。

環境

  • Raspberry Pi 3B+
  • Raspberry Pi OS
pi@raspberrypi:~/work $ cat /etc/os-release
PRETTY_NAME="Raspbian GNU/Linux 11 (bullseye)"
NAME="Raspbian GNU/Linux"
VERSION_ID="11"
VERSION="11 (bullseye)"
VERSION_CODENAME=bullseye
ID=raspbian
ID_LIKE=debian
HOME_URL="http://www.raspbian.org/"
SUPPORT_URL="http://www.raspbian.org/RaspbianForums"
BUG_REPORT_URL="http://www.raspbian.org/RaspbianBugs"
  • その辺のWEBカメラ IO-DATA製

写真を撮る方法

OpenCVなどが思いつきましたが、ラズパイにインストールするのは大変重いので、やりたくありません。
そこで、fswebcamというコマンドを使います。

インストール

$ sudo apt install fswebcam

その後、以下のコマンドで写真が保存されます

$ fswebcam -r 1280x720 -F 5  image.jpg

このコマンドの詳しい設定等はこちらの記事をご覧ください

便利な写真の確認方法

ssh越しに接続しているラズパイで、撮った写真を確認するためには、一度PC上に写真データを持ってくる必要があり、
写真を撮ってアングル等を調整するたびにこれをやるのは面倒です。

そこでmacでiTerm2使いの人限定ですが、
iterm2では、画像をターミナルで確認することができます。

iTermの公式サイトに方法が書かれています。

ここではimgcatというスクリプトの使い方を紹介します。
こちらのページのスクリプトを丸々コピーします。

/usr/local/bin/imgcatにこのスクリプトを貼り付けます。

$ sudo vi /usr/local/bin/imgcat

などでエディタを開き、コピペして保存します。

最後に実行権限を与えてあげます。

$ sudo chmod +x /usr/local/bin/imgcat

これでimgcatコマンドを使うことができます。

$ imgcat image.jpg

とすると、ターミナル上で画像が確認できます。

WEBカメラの解像度の確認

先ほどのコマンドでは、-r 1280x720で解像度を指定しました。
どの解像度で写真を撮れるのか、WEBカメラの情報を確認する必要があります。
そこでv4l-ctlというコマンドを利用します。

sudo apt-get install v4l-utils

でインストールします。

pi@raspberrypi:~/work $ v4l2-ctl --list-devices
bcm2835-codec-decode (platform:bcm2835-codec):
    /dev/video10
    /dev/video11
    /dev/video12
    /dev/video18
    /dev/media1

bcm2835-isp (platform:bcm2835-isp):
    /dev/video13
    /dev/video14
    /dev/video15
    /dev/video16
    /dev/media0

USB_Camera: USB_Camera (usb-3f980000.usb-1.1.2):
    /dev/video0
    /dev/video1
    /dev/media2

USB接続のWEBカメラが、/dev/video0と /dev/video1という名前で認識されていますが、
/dev/video0が本体のようです。

下記のコマンドで、このWEBカメラが使用できる解像度がわかります

pi@raspberrypi:~/work $ v4l2-ctl -d /dev/video0 --list-formats-ext
ioctl: VIDIOC_ENUM_FMT
    Type: Video Capture

    [0]: 'YUYV' (YUYV 4:2:2)
        Size: Discrete 640x480
            Interval: Discrete 0.033s (30.000 fps)
        Size: Discrete 160x120
            Interval: Discrete 0.033s (30.000 fps)
        Size: Discrete 176x144
            Interval: Discrete 0.033s (30.000 fps)
        Size: Discrete 320x240
            Interval: Discrete 0.033s (30.000 fps)
        Size: Discrete 352x288
            Interval: Discrete 0.033s (30.000 fps)
        Size: Discrete 800x600
            Interval: Discrete 0.100s (10.000 fps)
        Size: Discrete 1280x720
            Interval: Discrete 0.125s (8.000 fps)
        Size: Discrete 1920x1080
            Interval: Discrete 0.200s (5.000 fps)
    [1]: 'MJPG' (Motion-JPEG, compressed)
        Size: Discrete 640x480
            Interval: Discrete 0.033s (30.000 fps)
        Size: Discrete 160x120
            Interval: Discrete 0.033s (30.000 fps)
        Size: Discrete 176x144
            Interval: Discrete 0.033s (30.000 fps)
        Size: Discrete 320x240
            Interval: Discrete 0.033s (30.000 fps)
        Size: Discrete 352x288
            Interval: Discrete 0.033s (30.000 fps)
        Size: Discrete 800x600
            Interval: Discrete 0.033s (30.000 fps)
        Size: Discrete 1280x720
            Interval: Discrete 0.033s (30.000 fps)
        Size: Discrete 1920x1080
            Interval: Discrete 0.033s (30.000 fps)

解像度を決める

使える解像度がわかったところで、どの解像度にするか決めましょう。
これは、ラズパイに差してあるSDカードの容量と相談です。

さまざまな解像度で写真を撮ってみました。

pi@raspberrypi:~/work $ ls -alh *.jpg |sort -k 5 -h
-rw-r--r-- 1 pi pi  59K Dec 10 02:14 320x240.jpg
-rw-r--r-- 1 pi pi 191K Dec 10 02:12 640x480.jpg
-rw-r--r-- 1 pi pi 288K Dec 10 02:14 800x600.jpg
-rw-r--r-- 1 pi pi 564K Dec 10 02:12 1280x720.jpg
-rw-r--r-- 1 pi pi 1.2M Dec 10 02:13 1920x1080.jpg

一枚で1Mと聞くと大したサイズではないと思いますが、定点観測をするとなると、定期的に写真を撮ることになりますので
どんどん増えていきます。
5分おきに1日16時間撮ると考えると、1ヶ月では、(60/5)* 16 * 31 *1M = 5.95G
と、大きなサイズとなってしまいます。私が使っているSDカードは32GBですので、、半年しか持たない計算となります。

私の場合、余裕を持って640x480で保存することにしました。

画像を5分おきに撮るスクリプトの設定

画像を撮るスクリプトをcronで登録します。
下記が画像を保存するスクリプトです。
plant_imgディレクトリ内に、202112091220.jpgのようにYYYYMMDDHHMM.jpgの形式で保存します。

take_photo.sh
#!/bin/bash
dir="plant_img"
fswebcam -r 640x480 -F 5 $dir/$( date '+%Y%m%d%H%M').jpg

これに実行権限を与えてあげます。また、保存するディレクトリを作成しておきます。

$ chmod +x take_photo.sh
$ mkdir plant_img

cronに下記の通り設定します。
電気がついておらず暗い時間に写真をとっても真っ黒な画像しか撮れませんので、7時から24時までの間で5分おきに撮ります。

*/5 7-23 * * * cd /home/pi/work; ./take_photo.sh

これで定点観測した画像データが保存され続けます。

保存した画像から動画を作る

画像が無事撮影できましたら、タイムラプスとして動画を作りましょう。
まずはファイル名を連番にする必要があります。

$ cd plant_img
$ mkdir ../movie
$ ls | awk '{ printf "cp %s ../movie/test%05d.jpg\n", $0, NR }'
cp 202112090700.jpg ../movie/test00001.jpg
cp 202112090705.jpg ../movie/test00002.jpg
cp 202112090710.jpg ../movie/test00003.jpg
cp 202112090715.jpg ../movie/test00004.jpg
cp 202112090720.jpg ../movie/test00005.jpg
cp 202112090725.jpg ../movie/test00006.jpg
cp 202112090730.jpg ../movie/test00007.jpg
cp 202112090735.jpg ../movie/test00008.jpg
・
・


この時点ではまだコピーされていません。コマンドを生成したのみです。問題なさそうでしたら、パイプで渡して実行します。

$ ls | awk '{ printf "cp %s ../movie/test%05d.jpg\n", $0, NR }'|sh

こちらを実行すると、movieディレクトリに画像が連番でコピーされます。

動画にするには、ffmpegを使います。

sudo apt install ffmpeg

でインストールしましょう。

できたら、動画を作成します。

$ cd movie
$ ffmpeg -r 30 -i test%05d.jpg -pix_fmt yuv420p output.mp4

詳しいオプションは、ffmpegで調べてください。
すると、このような動画が出来上がります。