
九保すこひです(フリーランスのITコンサルタント、エンジニア)
さてさて、前回記事JavaScriptでレンダリングしてるページをスクレイピングする方法では、「ヘッドレスChrome」を使った関係から久しぶりNode.js
を使うことになりました。
そして、この記事を公開した後いつものPHP
やJavaScript
以外のプログラムも面白かったので、今回の記事も久しぶりにPython
を使った内容をお届けします。
その内容とは・・・
音を感知して録画する監視カメラをつくる
です!
実をいうとこの機能はブラウザ側のJavaScript
で実装できれば、と考えていたのですが、ウェブ上を探してもうまくいきそうな情報が見つからなかったので開発せず「置いとく」機能になっていました。
そして、少し前にこれがPython
だと意外と簡単に実装ができることがわかったのでここで皆さんと共有したいと思います。
ぜひ皆さんのお役に立てると嬉しいです
開発環境: Python 2.7
目次 [非表示]
パッケージをインストールする
以下2つの機能が必要なので、それぞれパッケージをインストールしておきます。
- 録画する部分 ・・・ OpenCV2
- 入力された音を監視する部分 ・・・ SoundDevice
パッケージはpip
でインストールできます。
以下のコマンドを実行してください。
pip install opencv-python
pip install sounddevice
準備
今回はcamera.py
というファイルにコードを書いて以下のコマンドで実行します。
python camera.py
なお、今回のコードで作成する録画ファイルは同じフォルダ内に作成したmovies
というフォルダ内に保存されることになります。権限の関係でエラーが発生することも考えられるので、このフォルダも作成し書き込み権限を与えておいてください。
コードを書いていく
ではここからPython
のコードを書いていく部分になりますが、今回もコードは短めなので、基本コードの中に書かれている番号を後で紹介するコードに入れ替えていけば全て完成する「学習雑誌の付録」形式でお届けします
基本のコード
まずは基本コードですが、今回は独自クラスSoundSurveillance
を作って実装します。
#!/usr/bin/env python
# -*- coding: utf-8 -*-
import cv2
import time
from datetime import datetime
import numpy as np
import sounddevice as sd
class SoundSurveillance:
# 定数と変数 ・・・ ①
# コンストラクタ ・・・ ②
# 音を監視する部分 ・・・ ③
# 録画する部分 ・・・ ④
ss = SoundSurveillance()
定数と変数 ・・・ ①
では、クラス内で必要になる定数と変数を定義しておきましょう。
# 定数と変数 ・・・ ①
DURATION = 3
VOLUME_THRESHOLD = 100
recording = False
DURATION
は、音がなったときに録画する秒数になります。
そのため、例えば飼い犬や猫の様子を撮影したい場合はもう少し長い時間にするといいかもしれません。
そして、VOLUME_THRESHOLD
は、いわゆる「しきい値」と呼ばれるもので、これと今鳴っている音の大きさを比べて録画するかどうかを判別することになります。
recording
は変数で、いま録画中かどうかが分かるようにTrue
とFalse
が入ることになります。
コンストラクタ ・・・ ②
コンストラクタは、一番最初に実行されるメソッドですので、ここで次の項目でつくる「音を監視するメソッド」listen_sound()
を呼び出しています。
# コンストラクタ ・・・ ②
def __init__(self):
self.listen_sound()
音を監視する部分 ・・・ ③
音を監視する部分はメソッドが2つです。
# 音を監視する部分 ・・・ ③
def listen_sound(self):
duration = 60 # 音声チェックを一時的に続ける秒数
while True:
with sd.InputStream(callback=self.detect_sound):
sd.sleep(duration * 1000)
def detect_sound(self, indata, frames, time, status):
if self.recording == False:
volume = np.linalg.norm(indata) * 10
if volume > self.VOLUME_THRESHOLD:
self.recording = True
self.start_recording()
まず、先ほどコンストラクタで呼び出していたlisten_sound()
ですが、ここでは最初にインストールしたパッケージSoundDevice
を使って入力音声を取得してます。今回は60秒ごとに何度も音声をチェックするようにしています。
そして、取得した音声データから「大きい音がなったかどうか」をチェックして、録画を実行するかどうか判別しているのがdetect_sound()
です。
この中では、indata
と呼ばれる変数の中に音声データが入っているので、これを元にして鳴っている音の音量(volume
)を取得、さらに①の項目で設定したVOLUME_THRESHOLD
と比較して、それより大きな数値だったら録画を開始するという流れになります。
録画する部分 ・・・ ④
では最後に今回のメイン、録画する部分をつくっていきます。
# 録画する部分 ・・・ ④
def start_recording(self):
self.recording = True
save_path = './movies/'+ datetime.now().strftime('%Y%m%d%H%M%S') +'.avi'
print('Recording...('+ save_path +')')
cap = cv2.VideoCapture(0)
# ウェブカメラのサイズを取得する
f_width = int(cap.get(cv2.CAP_PROP_FRAME_WIDTH))
f_height = int(cap.get(cv2.CAP_PROP_FRAME_HEIGHT))
fourcc = cv2.VideoWriter_fourcc(*'XVID')
video_writer = cv2.VideoWriter(save_path, fourcc, 25, (f_width, f_height))
started_time = time.time()
# ウェブカメラの映像を保存
while(cap.isOpened()):
ret, frame = cap.read()
diff_time = time.time() - started_time
if ret == False or diff_time >= self.DURATION:
break
else:
video_writer.write(frame)
cap.release()
video_writer.release()
cv2.destroyAllWindows()
self.recording = False
print('Recording finished.')
少しだけコードが長いですが、やっていることは、OpenCV
でウェブカメラにアクセスし1コマずつ映像を保存しているだけです。
ただし、録画は①の作業て追加したDURATION
(録画する秒数)を超えると自動的に終了するようになっていることに注意してください。
if ret == False or diff_time >= self.DURATION:
break
テストしてみる
では、簡単にテストしてみた結果です。
ファイルを起動して音がなる度に以下のように「Recording…」と「Recording finished」が表示されmovies
に動画ファイルが作成されました。
成功です
ダウンロードする
今回実際に開発したソースコードを以下からダウンロードすることができます。
※ ただし、パッケージのインストールやフォルダの作成などはご自身で用意してください。
音を感知して録画する監視カメラおわりに
ということで、久しぶりPython
を使ってコードを書いてみました。
プログラマーあるあるかもしれませんが、function xxxx() {
…. と書いたところで「違った!これPython
じゃない・・・」となってしまいました(笑)
ちなみに今回は私がメインで使っているUbuntu 18.04
で実行しましたが、Python
は様々なOSで実行できるので、小型PCのRaspberry Pi
などで実装して監視カメラをつくることもできると思います。
ぜひ皆さんも活用してみてくださいね。
ではでは〜!
※ なお、今回の機能をつくりたくなったのは、実はテレビ番組で「絶滅した動物を見つけよう!」という企画で音声に反応する監視カメラを使っていたことが発端でした。