Rasberry PiでUSBカメラで写真を撮影してFTPアップロードする方法をご紹介します。
静止画取得~FTPアップロード~静止画削除を行います。
目次
条件
- raspberry pi 3
- USBカメラ
- Python 3.6.4
事前準備
USBカメラ接続
USBカメラをraspberry piに接続します。
今回は「LOGICOOL HDウェブカム C525」を使用しました。
USBカメラは上記以外のものでも大丈夫だと思われます。
コマンドラインで「lsusb」を実行します。
pi@raspberrypi:~/camera_test $ lsusb Bus 001 Device 080: ID 046d:0826 Logitech, Inc. Bus 001 Device 003: ID 0424:ec00 Standard Microsystems Corp. SMSC9512/9514 Fast Ethernet Adapter Bus 001 Device 002: ID 0424:9514 Standard Microsystems Corp. Bus 001 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub
「Bus 001 Device 080: ID 046d:0826 Logitech, Inc. 」という表示があり、USBカメラが認識されていることがわかります。
fswebcamのインストール
静止画を取得するための「fswebcam」というパッケージをインストールします。
$ sudo apt update $ sudo apt install fswebcam
以上で事前準備は完了です。
写真撮影&FTPアップロード
写真撮影してから、指定のサーバーに写真をアップロードするため、Pythonでプログラムを作成します。
ソース
全体のソースは以下の通りです。
(cameraTest.pyという名前で保存します。)
# cameraTest.py
## FTPアップロードサンプル
import subprocess
import sys
import os
import time
from datetime import datetime as dt
from ftplib import FTP
import ftplib
from logging import getLogger, StreamHandler, Formatter, DEBUG
## ログ出力設定
logger = getLogger("Camera Test")
logger.setLevel(DEBUG)
stream_handler = StreamHandler()
stream_handler.setLevel(DEBUG)
formatter = Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')
stream_handler.setFormatter(formatter)
logger.addHandler(stream_handler)
## 接続先ホスト
HOST = 'hostName'
PORT = 21
USER = 'user'
PASSWORD = 'password'
DIRECTORY = 'test'
## アップロードファイル名の生成
PREFIX = 'c1_'
## ネットワーク設定がおかしい場合の回避策
_old_makepasv = FTP.makepasv
def _new_makepasv(self):
host,port = _old_makepasv(self)
host = self.sock.getpeername()[0]
return host,port
FTP.makepasv = _new_makepasv
def command(cmd):
"""
Exec command
"""
try:
result = subprocess.run(cmd, shell=True, check=True,
stdout=subprocess.PIPE, stderr=subprocess.PIPE,
universal_newlines=True)
for line in result.stdout.splitlines():
yield line
except subprocess.CalledProcessError:
logger.error('Command [' + cmd + '] was failed.', file=sys.stderr)
sys.exit(1)
def upload(fileName):
""""
FTP接続、ファイルアップロード
"""
logger.debug('== Start FTP ==')
with FTP() as ftp:
try:
ftp.connect(HOST, PORT) # ホスト、ポートを指定して接続
ftp.login(USER, PASSWORD) # ユーザID、パスワードを指定してログイン
ftp.cwd(DIRECTORY) # 指定のディレクトリに移動
with open(fileName, 'rb') as f:
ftpResult = ftp.storbinary('STOR ' + fileName, f) # 対象ファイルをアップロード
logger.debug(ftpResult)
except ftplib.all_errors as e:
logger.error('FTP error = %s' % e)
else:
logger.debug('FTP success.')
logger.debug('== End FTP ==')
if ftpResult == '226 Transfer complete.':
return True
else:
return False
def main():
"""
main関数
"""
fileName = PREFIX + dt.now().strftime('%Y%m%d_%H%M%S') + '.jpg'
cmd = 'fswebcam -r 800x600 --no-banner ' + fileName # 実行するコマンド
num = 0
while num < 10:
if os.path.isfile(fileName):
logger.info('exits.')
break
else:
logger.debug('not exits.')
for result in command(cmd):
logger.info(result)
time.sleep(3) # wait output
num += 1
if num == 10:
logger.error('File not found.')
return
if upload(fileName): # File Upload
logger.info('Upload success.')
cmd = 'rm ' + fileName
logger.debug(cmd)
for result in command(cmd): # Delete Image
logger.info(result)
else:
logger.warning('Upload failed.')
if __name__ == "__main__":
main()
解説
ソースの概略(main関数)は以下の通りです。
- 撮影画像のファイル名(fileName)を現在日時で作成します。
- fswebcamコマンドを実行し、静止画像を取得します。
- -rオプションで画像サイズを指定し、–no-bannerオプションで画像からバナーを削除します。
- 静止画像取得の処理に少し時間がかかる&失敗することもあるため、whileループでsleep()を入れながら撮影のリトライを行います。
- 10回失敗した場合、エラーとします。
- 静止画像の取得に成功した場合、指定サーバーへFTPアップロードを行います。
- FTPアップロードに成功した場合、静止画像をrasberry piから削除します。
注意事項
静止画像の取得は、短い時間で連続して実施することは出来ないようです。
一度、静止画像を取得した後、カメラの準備処理が行われるため、数秒間待つ必要があります。
実行結果
処理成功
処理に成功した場合、以下のような出力となります。
pi@raspberrypi:~/camera_test $ python3 cameraTest.py 2019-12-12 16:49:29,736 - Camera Test - DEBUG - not exits. 2019-12-12 16:49:34,197 - Camera Test - INFO - exits. 2019-12-12 16:49:34,197 - Camera Test - DEBUG - == Start FTP == 2019-12-12 16:49:35,422 - Camera Test - DEBUG - 226 Transfer complete. 2019-12-12 16:49:35,422 - Camera Test - DEBUG - FTP success. 2019-12-12 16:49:35,468 - Camera Test - DEBUG - == End FTP == 2019-12-12 16:49:35,469 - Camera Test - INFO - Upload success. 2019-12-12 16:49:35,469 - Camera Test - DEBUG - rm c1_20191212_164929.jpg
撮影失敗の場合
撮影に失敗した場合(静止画取得に10回失敗)、以下のような出力となります。
pi@raspberrypi:~/camera_test $ python3 cameraTest.py 2019-12-12 16:48:28,625 - Camera Test - DEBUG - not exits. 2019-12-12 16:48:30,649 - Camera Test - DEBUG - not exits. 2019-12-12 16:48:32,678 - Camera Test - DEBUG - not exits. 2019-12-12 16:48:34,705 - Camera Test - DEBUG - not exits. 2019-12-12 16:48:36,732 - Camera Test - DEBUG - not exits. 2019-12-12 16:48:38,766 - Camera Test - DEBUG - not exits. 2019-12-12 16:48:40,792 - Camera Test - DEBUG - not exits. 2019-12-12 16:48:42,828 - Camera Test - DEBUG - not exits. 2019-12-12 16:48:44,853 - Camera Test - DEBUG - not exits. 2019-12-12 16:48:46,879 - Camera Test - DEBUG - not exits. 2019-12-12 16:48:48,905 - Camera Test - ERROR - File not found.
参考
Raspberry Pi 公式ドキュメントを日本語訳:一般的なWebカメラを使用する
http://igarashi-systems.com/sample/translation/raspberry-pi/usage/webcam.html

