Rasberry PiでUSBカメラで写真を撮影してFTPアップロードする方法
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
大変参考になりました。このページを作成していただき、ありがとうございます。