以前にラズパイのカメラモジュールで撮影した写真をメールに添付して送信する方法を記事にしたことがあるのですが、今回は、ラズパイで簡単に動体検知できる「Motion」と呼ばれるソフトウェアをインストールして、撮影した動画(.mp4)を添付して送るという本格的な防犯カメラシステムを構築する方法を記事にしたいと思います。

スポンサーリンク




目次

  1. 防犯カメラシステムの仕様について
  2. 必要なものを揃えよう
  3. OSのインストールや諸設定について
  4. Motionのインストールと設定について
  5. Pythonでコード作成
  6. cron設定
  7. まとめ

1. 防犯カメラシステムの仕様について

ひとまず、次のような仕様を想定してみました。

  1. Motionで常に動体検知し、検知した場合は最長10秒の動画(.mp4)を撮影する
  2. 5分毎に撮影された動画があるかチェックし、撮影された動画ある場合は、設定されたメールアドレスに撮影動画をメールに添付(複数動画に対応)して送信する
  3. 送信された動画はディスク容量の節約のため、全て削除しておく

このような仕様でシステムを構築してみたいと思います。

2. 必要なものを揃えよう

ラズパイ本体

まずはラズパイ本体とカメラモジュールを用意しましょう。防犯カメラは小さい方が目立たなくて良いと思うので、Raspberry Pi Zero Wを使ってみることにします。残念なことに、国内だと品切れなことが多いです。高めでもよければ、amazonでも手に入れることができます。

Raspberry Pi Zero W – ヘッダー ハンダ付け済み – ラズベリー・パイ ゼロ W ワイヤレス

カメラモジュール

純正のカメラモジュールではないですが、amazonだと汎用性が高く、純正よりも安い互換品が手に入りますので、気になる方は、下記を参考にしてみてください。

RasTec Raspberry Pi カメラモジュール ラズベリーパイカメラ 500万画素 Raspberry Pi4B/3B+/3B/2B/2B+/ZERO1.3/ZERO Wに適用 クリアケースブラケット*1とリボンケーブル*3が付き

※上記のリンクはamazonへのリンクとなっています。

また、ラズパイ本体・カメラモジュールの入手に時間がかかってもよければ「PIMORONI」のような海外の有名オンライン・ショップから国際郵便で取り寄せることもできます。本体とカメラモジュールのみの場合、送料は800円程度だったと思います。自分はPIMORONIが好きで、これまでに10回以上利用していますが、一度も不着などのトラブルは発生していません。現在、コロナの影響がどの程度あるのか分かりませんが、自分の場合は概ね2週間程度で到着したと記憶しています。

3. OSのインストールや諸設定について

次に、OSのインストールやラズパイの諸設定に関する情報について言及しておきたいと思います。必要ない人は読み飛ばしてください。

OSのインストールと初期設定

OSのインストールと初期設定のやり方について情報が必要な方は、以前の記事「Raspberry Pi OSのインストール方法、USB OTG(On-The-Go)の設定方法、Wi-Fi設定などラズパイの初期設定まとめ」を参考にしてみてください。

カメラモジュールの設定

カメラモジュールを使えるようにするには「raspi-config」で設定が必要です。設定方法に関する情報が必要な方は、以前の記事「Raspberry Piとカメラモジュールで電子工作:撮影した写真をメールに添付して送信する方法」を参考にしてみてください。

4. Motionのインストールと設定について

それでは、いよいよこの記事の本編に入っていきたいと思います。まずはMotionをインストールしましょう。「apt-get」でインストールします。

sudo apt-get install motion

※ ちなみに「apt-get」ではなく「apt」でもOKです。

インストールが完了したら、今度はMotionの基本設定を行います。

sudo vi /etc/motion/motion.conf

起動設定

# Start in daemon (background) mode and release terminal (default: off)
daemon on

# Restrict stream connections to localhost only (default: on)
stream_localhost off

# Set the authentication method (default: 0)
# 0 = disabled
# 1 = Basic authentication
# 2 = MD5 digest (the safer authentication)
stream_auth_method 1

# Authentication for the stream. Syntax username:password
# Default: not defined (Disabled)
; stream_authentication username:password

※ 上記の各設定は必ずしも連続しているわけではないので「/」を使って、設定箇所をキーワード検索してみてください。

demon

Motionを自動起動させてバックグラウンドで動作するサービスとして使用する場合は、この「demon」を「on」とします。また、サービスとして自動起動させるには「sudo vi /etc/rc.local」で「exit 0」よりも上に「motion &」と記述する必要もあります。

サービスではなく、普通にアプリケーションとして起動させる場合は「sudo motion -n」で起動させ、終了時は「ctrl + c」で終了させます。

stream_localhost

ブラウザで動体検知の状況を確認したい場合設定です。これを「off」に設定すると、他の端末から、ラズパイのローカルIPアドレスを直接指定し「http://xxx.xxx.xxx.xxx:8081」のような指定でアクセスすることができるようになります。

stream_auth_method, stream_authentication

この画面にBasic認証を設定する場合はstream_auth_method」の設定を「1」にして「stream_authentication」の「username:password」を書き換えておいてください。

これは実際にブラウザでラズパイのローカルIPアドレスにアクセスし、カメラに写った映像を確認しているところです。

この機能を使う場合、ラズパイのローカルIPアドレスは固定にしておいた方が便利かもしれません。以前の記事Raspberry Pi OSのインストール方法、USB OTG(On-The-Go)の設定方法、Wi-Fi設定などラズパイの初期設定まとめ」にIPアドレスを固定にする方法もまとめてありますので、よかったら参考にしてみてください。

動画設定

以下は記録する動画に関連する設定です。

# The video norm to use (only for video capture and TV tuner cards)
# Values: 0 (PAL), 1 (NTSC), 2 (SECAM), 3 (PAL NC no colour). Default: 0 (PAL)
norm 1

# Image width (pixels). Valid range: Camera dependent, default: 320
width 640

# Image height (pixels). Valid range: Camera dependent, default: 240
height 480

# Maximum number of frames to be captured per second.
# Valid range: 2-100. Default: 100 (almost no limit).
framerate 6

# Maximum length in seconds of a movie
# When value is exceeded a new movie file is created. (Default: 0 = infinite)
max_movie_time 10

# Target base directory for pictures and films
# Recommended to use absolute path. (Default: current working directory)
target_dir /home/pi/motion

# Container/Codec output videos
# Valid values: mpeg4, msmpeg4, swf,flv, ffv1, mov, mp4, mkv, havoc
ffmpeg_video_codec mp4

※ 上記の各設定は必ずしも連続しているわけではないので「/」を使って設定箇所をキーワード検索してみてください。

norm

映像規格の設定です。基本的に「NTSC」にすべきなので、特に理由がなければ「1」と設定します。

width, height, framerate

解像度、フレームレートの設定は好みで設定してもらっていいと思いますが、特にフレームレートは、Raspberry Pi Zeroの場合「10」程度が限界のようです。そもそも防犯システムとして構築しようとしているので、高いフレームレートの設定は必要ないかと思います。

max_movie_time

動体を検知した時の動画記録の最大時間の設定です。ここでは「10」秒としましたが、これも自由に設定が可能です。ただ、今回はメールで動体検知した動画ファイルを添付して送ることを想定しているので、あまり長くしてしまうとファイルサイズが必要以上に大きくなってしまうので注意してください。

target_dir

動画ファイルの保存先の設定も任意で変更することができます。ここではデフォルトから変更し、取り扱いのしやすいユーザーディレクトリ内の「/home/pi/motion」に変更してあります。ただし、記録される動画ファイルはroot所有のファイルとなりますので、注意してください。

ffmpeg_video_codec

動画形式の設定は、汎用性の高い「mp4」としました。

動体検知設定

次は動体検知に関わる設定です。

# Threshold for number of changed pixels in an image that
# triggers motion detection (default: 1500)
threshold 30720

# Event Gap is the seconds of no motion detection that triggers the end of an event.
# An event is defined as a series of motion images taken within a short timeframe.
# Recommended value is 60 seconds (Default). The value -1 is allowed and disables
# events causing all Motion to be written to one single movie file and no pre_capture.
# If set to 0, motion is running in gapless mode. Movies don't have gaps anymore. An
# event ends right after no more motion is detected and post_capture is over.
event_gap 60

# Draw characters at twice normal size on images. (default: off)
text_double on

# Locate and draw a box around the moving object.
# Valid values: on, off, preview (default: off)
# Set to 'preview' will only draw a box in preview_shot pictures.
locate_motion_mode on

# Set the look and style of the locate box if enabled.
# Valid values: box, redbox, cross, redcross (default: box)
# Set to 'box' will draw the traditional box.
# Set to 'redbox' will draw a red box.
# Set to 'cross' will draw a little cross to mark center.
# Set to 'redcross' will draw a little red cross to mark center.
locate_motion_style box

threshold

まずは動体検知の閾値の設定です。ここで設定したピクセル数に変化があった場合に動体として検知されます。この記事の設定では、動画サイズは「640 * 480」と設定したので、総ピクセル数は「307,200」ということになりますが、ここでは10%のピクセル数に変化が現れた場合を閾値として設定しています。

ちなみにデフォルトでは「1500」となっているのですが、このままだと木の葉の揺らぎ、蛍光灯のチラつき程度でも動体を検知してしまう可能性があるので、何を検知したいかに応じて、設定は適宜変更する必要があります。色々試してみましたが、防犯目的なら比較的大きな値を設定した方が良さそうです。最適値は目的に応じて各自で判断してみてください。

event_gap

この設定はちょっと理解が難しいのですが、設定した時間の間に複数の動きを検知した時に、その動きを独立した動体として認識するかどうかの判断基準としての時間を設定します。例えば、動いたり止まったりするような一連の動きをする動体があった場合、それらの動きを別々の動体として判断するか、一連の動きとして判断するかの基準とするための時間設定です。短すぎる設定だと動画ファイルが無駄に沢山出力されてしまいます。こだわりがなければデフォルトのままでいいと思います。

text_double

録画日時のフォントサイズの設定は、デフォルトでは小さすぎると感じたので、ここでは「on」とし、倍サイズの設定にしてあります。ちなみに、前述のブラウザの実況画面は倍サイズ設定の大きさになっています。

locate_motion_mode, locate_motion_style

動体をマーキングする設定「locate_motion_mode」は「on」にすると動体にマーキングすることができます。「locate_motion_style」は「box」にしておくと白枠で囲われるようになります。枠ではなく十時にしたり、赤色にすることも可能です。

5. Pythonでコード作成

設定が完了したら、いよいよコードを書いていきます。今回用意したサンプルコードはこんな感じになりました。

# -*- coding: utf-8 -*-
import os
import time
import smtplib
from email.MIMEText import MIMEText
from email.Header import Header
from email.Utils import formatdate
from email.mime.application import MIMEApplication
from email.mime.multipart import MIMEMultipart
from os.path import basename
from glob import glob

# メール送信設定
SMTP_SERVER = 'smtp.server.jp'
SMTP_PORT = 587
SMTP_ID = 'your id'
SMTP_PW = 'your password'
MAIL_FROM = 'your email'
MAIL_TO = 'your email'

# メール送信
def send_attached_mail(subject, massage, attachments):

	# 文字コード設定
	charset = 'ISO-2022-JP'

	mail = MIMEMultipart()
	mail['Subject'] = Header(subject, charset)
	mail['From'] = MAIL_FROM
	mail['To'] = MAIL_TO
	mail['Date'] = formatdate(localtime=True)

	# メール本文を添付
	body = MIMEText(massage.encode(charset), 'plain', charset)
	mail.attach(body)

	# ファイルを添付
	for attachment in attachments:
		with open(attachment, "rb") as f:
			file = MIMEApplication(
				f.read(),
				Name=basename(attachment)
			)
		file['Content-Disposition'] = 'attachment; filename="%s"' % basename(attachment)
		mail.attach(file)

	smtp = smtplib.SMTP(SMTP_SERVER, SMTP_PORT)
	smtp.login(SMTP_ID, SMTP_PW)
	smtp.sendmail(MAIL_FROM, MAIL_TO, mail.as_string())
	smtp.close()

# メイン関数
def main():

	# メール設定
	subject = u'動体を検知しました!'
	massage = u'撮影した動画です。\n'
	attachments = glob('./*.mp4')

	# 添付ファイル確認
	if len(attachments) >= 1:

		# メール送信
		send_attached_mail(subject, massage, attachments)
		time.sleep(10)

		# 送信後ファイル削除
		os.system('sudo rm *.mp4')

if __name__ == '__main__':
	main()

14〜19行目:
メール送信のためのSTMPサーバーが必要になりますので、ご自身で利用しているSMTPサーバーを指定してください。

22行目:
send_attached_mail」という関数でメールを送信しますが、まず58行目で、glob関数を使い同じディレクトリにある「.mp4」の拡張子が付いたファイル名を探して「attachments」というリストに格納しています。添付すべき動画が1つでもあればsend_attached_mail」を実行するようになっています。38行目で複数の動画を一つずつ添付する処理を実行しています。

65行目:
メール送信後の「time.sleep(10)」ですが、メール添付と送信に多少時間がかかるだろうという想定で10秒の実行休止をかけています。適宜変更してください。

6. cron設定

このプログラムはcronを使い、一定間隔で実行されるようにしてみました。cron設定を上書き保存したら、設定を反映します。

crontab -e
*/5 * * * * python /home/pi/motion/motion-alert.py
sudo /etc/init.d/cron restart

最後にcronリストを表示して新しい設定が反映されているか確認してみましょう。

crontab -l

実行結果

コードが完成したら、早速プログラムを実行してみましょう。動体を検知するとこのようなメールが送信されてきます。

これは実際に添付されてきた動画です。このように動体を白枠で囲った映像が送られてきます。

7. まとめ

いかがだったでしょうか。ご紹介してきたように動体検知から動画のエンコードまで難しいことは全てMotionがやってくれるので、一定間隔で録画された動画をチェックし、添付メールを送信するコードを実装するだけで、本格的な防犯カメラシステムが完成してしまいます!

どのような目的で使うかにもよりますが、Raspberry Pi Zero Wは1A出力のモバイルバッテリーはもちろんのこと、このように乾電池でも動かすこともできますよ!

※ このカメラは記事内リンクで紹介したamazonの互換品ではなく、PIMORONIで購入したRaspberry Pi Zero専用の小型カメラモジュールです。また、この電源(アルカリ9v乾電池)での運用はせいぜい数時間が限界なので、長時間運用したい場合は他の電源を検討してください。なお、電池容量が落ちた状態だと再起動を繰り返してOSを壊してしまう可能性があるので十分注意してください。

乾電池で昇圧・降圧してラズパイを動かす方法は、以前の記事「Raspberry Pi Zeroを乾電池や7.2Vバッテリーで起動させる2つの方法」で詳しく解説していますので、必要があれば参考にしてみてください。

これなら防犯はもちろんのこと、ペットの見守りなどにも使えますね!…あと、念のため。けっして良からぬ目的では使用しないようにしましょう(笑)