Raspberry Piのカメラで遊ぼう(初期編)

目次
カメラモジュールで画像処理いろいろ
Raspberry Piには専用のカメラモジュールが用意されています。
このカメラモジュールを接続すると、カメラの画像を通していろいろな処理をさせる事が可能になります。
いわば、「目」をもたせるようなものです。
今回はカメラモジュールを使ったいろいろな処理をご紹介します。
前提条件
前提条件として、Raspberry Piのセットアップが終わっている事が必要です。
セットアップについては、
の記事を参照してください。

上記のインストールの際、OSの選択として、Raspberry Pi OS(Legacy)を選択します。
これは、記事を作成じた時点の最新版ではカメラモジュールの扱いが変わっているためです。
少なくとも、私の環境では、新OSのカメラコントローラーは、OpenCVがカメラを認識できませんでした。
このため、一つ古いLegacy版のOSをインストールします。
いずれ、新OSでの情報が集まれば、認識が可能になるかもしれません。
カメラモジュールの取り付け
カメラモジュールは簡単に入手出来ます。
暗いところを見守りたいなど、用途があるならそれ専用カメラを必要としますが、通常ならAmazonで安いカメラを購入しても充分に実用になります。
本体へは、15ピンのリボンケーブルで接続します。
大抵の場合、購入したカメラモジュールに付属しています。
カメラの位置を本体と離した位置にする必要がある場合などは、長いリボンケーブルと交換する事も可能です。
上記の画像は、Raspberry Pi 3Bの場合です。
Raspberry Pi 4は有線LANコネクタが左右逆位置なのでご注意ください。
付属のリボンケーブルの場合は、青い印がLAN、USBコネクタ側に向くようにします。
ケーブルを奥まで差し込んだら、持ち上げた固定バーを押し下げて、ケーブルを固定します。
カメラを有効にする。
カメラを取り付けたら、カメラが使えるよう設定します。
Raspberry Piのメインメニューから、設定>Raspberry Piの設定を選びます。
設定画面で、インターフェイスを選び、カメラを有効に変更します。
ちなみに、Raspberry Pi OS(Legacy)では上記の表示になりますが、最新のOS(bullseyeといいます)では、カメラの設定がありません。

表示が無い場合は、残念ですが、Raspberry Pi OS(Legacy)をインストールし直しする方が良いかとおもいます。
Legacy Cameraを有効にする設定もあるにはあるのですが、上手く認識されない事象が発生し、断念しました。
カメラのテストをする
接続して有効化されたカメラをテストするには、コマンドラインからコマンドを入力する。
raspistill -o test.jpg

コマンドを入力してEnterを入れると5秒後に撮影され、test.jpgにファイルが保存されます。
※このコマンドは、Raspberry Pi OS(Legacy)でないと存在しません。
最新のOS(bullseye)ではコマンドが見つからないと出ます。
Legacy Cameraを有効にする設定でコマンドが有効化されるのですが、私の環境ではうまく有効化されないため、Raspberry Pi OS(Legacy)にしました。
raspivid -o test.h264
をコマンドとして入力すると、test.h264 に動画が保存されます。
見守りカメラにする
カメラを使用した機構として一番簡単なのは、単純にカメラが捉えた動画を流す「見守りカメラ」です。
ペット用などで格安の商品もありますが、Raspberry Piでも簡単に作る事ができます。
RPi_Cam_Web_Interface のインストール
RPi_Cam_Web_Interface をインストールするだけで完成します。
git clone https://github.com/silvanmelchior/RPi_Cam_Web_Interface.git
これで、実行したときのフォルダに RPi_Cam_Web_Interface というフォルダが作成されます。
作成されたフォルダに移動し、ビルドします。
cd RPi_Cam_Web_Interface
sudo ./install.sh
ビルド中に確認を求める表示がでます。

なにも変更なしで了解で大丈夫かと思います。
ちなみに、Autostart なのでこのRaspberry Piを起動すると自動起動されます。
また、外部からカメラ画像を見るため、WEBサーバーのApacheがインストールされます。

これで起動も完了しています。
カメラ映像の呼び出し
Raspberry Piと同じLANに接続されているパソコンのブラウザから、
http://[Raspberry Piのipアドレス]/
と入力すると、このような画面が表示されます。

このhtmlフォルダマークをクリックすると

このように、カメラが現在撮影している画像をみる事ができます。
設定部分でカメラの回転や反転なども可能ですし、動画、静止画の撮影も可能です。
見守りや監視カメラとしては充分な性能と言えるでしょう。
見守りカメラに外部から接続する
インストールするだけで、簡単に見守りカメラにできるのは良いのですが、一つ問題があります。
これでは、同一のLAN内に居る場合しか使用できません。
本当に見守りカメラとして使用するのであれば、例えば外出中にスマートフォンで映像をチェックできないと、あまり意味がないものになってしまいます。
外部のネットワークから接続するには
LAN(Local Area Network)は、ある一定の場所の中のコンピュータを結びつけたネットワークで、「プライベートネットワーク」 ともいいます。
一方、インターネットの事を、WAN(Wide Area Network 「パブリックネットワーク」)と言ったりします。
諸説はありますが、このWANとLANは、ルーターを境に、構内側がLANで、外側がWANと分けられています。
WAN側からLAN側にアクセスすることは基本的にできません。
つまり、外にいるスマートフォンから自宅などのRaspberry Piに接続するには、出来ないはずのWAN側から自宅のLANに接続しないといけません。
これには、VPN(Virtual Private Network)などを利用する手段もありますが、見守りカメラひとつのためにVPNサーバーを立ち上げるのも大仰です。
そこで、今回はremote.itというサービスを使用します。
Raspberry Piにremote.itをインストールする
remote.itは、P2P技術を使用したネットワークの接続システムです。
VPNのようにポートを開けたり、サーバーを用意する必要がなく、無償なので手軽に始められます。
まずはアカウトを作成しましょう。
ブラウザでremote.itのサイトに接続します。

ヘルプがありますが、今回はアカウントの作成なので、「助けはいらない、自分でセットアップしたい。」を押下します。

今回は、はじめてremote.itを使用する想定なので、Sign up for free! からアカウントを登録します。
スマートフォンにremote.itをインストール
remote.itはスマートフォン用のアプリがあります。
Andoroido版で試してみます。
これで、例えば外出先から自宅のRaspberry Piのカメラ画像をリアルタイムで見る事ができます。
見守りカメラとして使用するだけなら、ここまでで充分な性能が出せます。
Pythonからカメラを制御する
Raspberry Piには、プログラム言語、Pythonが標準搭載されていて、いろいろな制御に使用できます。
今度はPythonからカメラを制御してみます。
前提条件
RPi_Cam_Web_Interfaceをインストールして稼働させている場合、カメラモジュールは常時使用中になります。
この場合、使用中で権限が取得できないため、Pythonなどの他プログラムからカメラは使用できません。
RPi_Cam_Web_Interfaceが動作中のまま、pythonでカメラを操作しようとすると
mmal: mmal_vc_port_enable: failed to enable port vc.null_sink:in:0(OPQV): ENOSPC
mmal: mmal_port_enable: failed to enable connected port (vc.null_sink:in:0(OPQV))0x92e820 (ENOSPC)
mmal: mmal_connection_enable: output port couldn't be enabled
Traceback (most recent call last):
File "camera.py", line 6, in <module>
camera = PiCamera()
File "/usr/lib/python3/dist-packages/picamera/camera.py", line 433, in __init__
self._init_preview()
File "/usr/lib/python3/dist-packages/picamera/camera.py", line 513, in _init_preview
self, self._camera.outputs[self.CAMERA_PREVIEW_PORT])
File "/usr/lib/python3/dist-packages/picamera/renderers.py", line 558, in __init__
self.renderer.inputs[0].connect(source).enable()
File "/usr/lib/python3/dist-packages/picamera/mmalobj.py", line 2212, in enable
prefix="Failed to enable connection")
File "/usr/lib/python3/dist-packages/picamera/exc.py", line 184, in mmal_check
raise PiCameraMMALError(status, prefix)
picamera.exc.PiCameraMMALError: Failed to enable connection: Out of resources
のようなエラーが発生します。
RPi_Cam_Web_Interfaceを停止する方法は、インストールした際に、RPi_Cam_Web_Interface というフォルダが作成されていますので、そこに移動します。
$ ls
'DoNot UseRPi_Cam_Web_Interface_Installer.sh' config.txt remove.sh
LICENSE.txt debug.sh start.sh
README.md etc start.txt
SECURITY.md install.sh stop.sh
bin install.txt update.sh
cam.sh installreadme.txt www
lsコマンドで確認すると、このようなファイルが配置されていますので、
$ ./stop.sh
で停止コマンドを実行します。
もう一度、RPi_Cam_Web_Interfaceに戻すには、
./start.sh
を実行します。
カメラモジュールを使用するコード
Raspberry Piの公式サイトのプロジェクトにカメラモジュールをはじめようというものがあり、子供向けなのか簡単に判りやすく記述されています。
その中のコードの一つがこちらになります。
from picamera import PiCamera
from time import sleep
camera = PiCamera()
camera.start_preview()
sleep(5)
camera.capture('/home/[ユーザー名]/Pictures/image.jpg')
camera.stop_preview()
サイトでは、home/pi/Desktop/image.jpg となっているのですが、現在はpiユーザーは廃止となっているため、サイトのコードそのままでは動作しません。
セットアップ時のユーザー名に変更しましょう。

Raspberry Pi標準搭載のPython3エディタ Thonny Python IDE にコードを貼り付けして実行すると、このようになります。
右下の写真は、ictures/image.jpgを開いたものです。
ちなみに、写真が保存される前にカメラプレビューが表示されます。
いろいろ組み合わせて発展させる
つまり、import PiCamera でカメラのライブラリを読み込み、camera.capture(指定のファイル名)でカメラ画像が撮影できるので、Raspberry Piの様々な機能と組み合わせる事が可能です。
GPIOと
Raspberry Piには40ピンのGPIOが装備されており、ここに機器を繋ぐ事で様々な機器をコントロールできます。
当ブログでこのGPIOを使用した例としては、
で、LEDマトリックスとRaspberry Piを接続するのに使用しました。
この他にも、GPIOピンにIN、OUT設定で色々制御する事が可能です。

タクトスイッチに、GPIOの1番と18番ピン(GPIO24)を接続します。
こうすると、タクトスイッチを押すとGPIO24番に電圧がかかった状態になり、離すと電圧はなくなります。
これをpythonのプログラムで検知すると、このようになります。
from picamera import PiCamera
from time import sleep
import datetime
import RPi.GPIO as GPIO
camera = PiCamera()
GPIO.setmode(GPIO.BCM)
GPIO.setup(24,GPIO.IN,pull_up_down=GPIO.PUD_DOWN)
try:
while True:
if GPIO.input(24)==GPIO.HIGH:
dt_now = datetime.datetime.now()
filn = '/home/kazuhiro/Pictures/' + dt_now.strftime('%Y%m%d%H%M%S')
+ '.jpg'
camera.capture(filn)
sleep(1)
except KeyboardInterrupt:
pass
GPIO.cleanup()
if GPIO.input(24)==GPIO.HIGH: の部分が検知で、タクトスイッチが押されて電圧がかかる=HIGH を検知すると、システム時間を呼び出してファイル名にし、カメラ映像を保存します。
つまり、カメラのシャッターにできるわけです。
電子工作にはいろいろなセンサーがあり、例えば超音波で距離を測るセンサーなどがありますので、センサーに近づいた事を検知したら、カメラを作動させるというような事も可能になります。
決まった時間に起動する。
Raspberry PiのOSは、基本的にはDebianというLinux なので、Linuxでできる事は大抵できます。
LinuxにはCron というコマンドがあり、これを使用すると、指定の時間間隔でプログラムを動作させる事が可能になります。
$ crontab -e
*/5 * * * * python3 /home/kazuhiro/Documents/camera_cron.py
※これを記述して保存する
内容は、5分事に/home/kazuhiro/Documents/camera_cron.pyをpython3で実行するという内容
from picamera import PiCamera
from time import sleep
import datetime
camera = PiCamera()
sleep(5)
dt_now = datetime.datetime.now()
filn = '/home/kazuhiro/Pictures/' + dt_now.strftime('%Y%m%d%H%M%S') + '.jpg'
camera.capture(filn)
こうすると、5分事に年月日時分秒.jpgでファイルが保存されます。
WordPressで利用する。
WordPressは、オープンソースのブログソフトウェアで、コンテンツ管理システム (CMS) としてもしばしば利用されています。
通常、ブログ記事は人間が執筆してブログ上で公開しますが、WordPressの場合、pythonなどのプログラムから投稿する事を可能にする「WP REST API」という仕組みを搭載しています。
これは、所定の方法でWordPressのサイトに接続すると、投稿内容を受け取ってくれる仕組みになります。
投稿ユーザーを用意する。
ご自身のWordPressサイトが既に稼働している事が前提です。
そのサイトに、投稿用のユーザーを追加します。

記事では、raspberry _Pi というアカウントを追加しました。
権限は投稿者のままとします。高い権限を与えるのはセキュリティ上の懸念になります。
ユーザーが追加できたら、アプリケーションパスワードを発行します。
ユーザーの一覧から、今回追加したユーザーを選び、編集をクリックします。

スクロールで下に下がると、アプリケーションパスワードという項目があるので、適当な名前を付け、アプリケーションパスワード追加ボタンを押下します。

パスワードが発行されました。

自動投稿のコード
import RPi.GPIO as GPIO
import requests
import os
import json
from picamera import PiCamera
from time import sleep
from urllib.parse import urljoin
import datetime
camera = PiCamera()
GPIO.setmode(GPIO.BCM)
GPIO.setup(24,GPIO.IN,pull_up_down=GPIO.PUD_DOWN)
filename = ''
unique_id = 0
img_url = 0
img_width = 0
img_height = 0
url_base = '[投稿するWordPressのドメイン]'# アプリケーションパスワードで発行したパスワード
user = 'raspberry_pi' # ユーザー名
password = '[先ほど発行したアプリケーションパスワード]' # アプリケーションパスワードで発行したパスワード
pic_path = '/home/kazuhiro/Pictures/'
def wp_post():
url = urljoin(url_base, 'wp-json/wp/v2/posts/')
content = '<h2>Raspberry Piから自動投稿する</h2>'
content += '<p>Raspberry Piの専用カメラモジュールがで撮影した写真を、pythonで自動投稿しています。</p>'
content += '<figure class="wp-block-image size-full is-resized">'
content += '<a href="https://yoshisyou.com/wordpress/wp-content/uploads/'
content += img_url
content += '"><img src="https://yoshisyou.com/wordpress/wp-content/uploads/'
content += img_url
content += '" alt="" class="wp-image-'
content += str(unique_id)
content += '" width="'
content += str(img_width / 2)
content += '" height="'
content += str(img_height / 2)
content += '"/></a></figure>'
post = {
'title': 'WordPress自動投稿テスト',
'status': 'draft', # draft(下書き), publish(公開)
'slug': 'wordpress-auto-post-test', # パーマリンク
'categories': 1, # カテゴリID
'date': datetime.datetime.now().isoformat(),
'content': content,
}
res = requests.post(
url,
json=post,
auth=(user, password),
)
return
def wp_upload_media():
url = urljoin(url_base, 'wp-json/wp/v2/media/')
file_path = os.path.join(pic_path, filename)
f = open(file_path, 'rb')
image_data = f.read()
f.close()
headers = {
'Content-Type': 'image/png',
'Content-Disposition': 'attachment; filename=' + filename,
}
res = requests.post(
url,
data=image_data,
headers=headers,
auth=(user, password),
)
res_dict = res.json()
global unique_id
unique_id = res_dict['id'] # アップロードした画像のID
global img_url
img_url = res_dict['media_details']['file']
global img_width
img_width = res_dict['media_details']['width']
global img_height
img_height = res_dict['media_details']['height']
return
def photographing():
dt_now = datetime.datetime.now()
global filename
filename = dt_now.strftime('%Y%m%d%H%M%S') + '.png'
camera.capture(os.path.join(pic_path, filename))
return
def main():
try:
while True:
if GPIO.input(24)==GPIO.HIGH:
photographing()
wp_upload_media()
wp_post()
sleep(1)
except KeyboardInterrupt:
pass
if __name__ == '__main__':
main()
非常にざっくりしたコードです。実際に常用するにはいくつか改良が必要ですが、試験だけならこれで動作します。
基本はGPIOでカメラを動作させるコードの改良版になります。
タクトスイッチの電圧を監視し、電圧がかかるとカメラを動作させて写真を撮影します。
その写真をWordPressのWP REST APIを使って、メディアに投稿します。
投稿が成功すると、イメージのサイズや名称、WordPress上の位置などがjsonで送り返されるので、それをパース(分解)して必要な要素を取り出し、投稿用のデータに挿入して、再びWP REST APIで投稿を送ります。
このプログラムを動作させると、次の投稿のようになります。
cronと組み合わせたりすれば、定期的に固定カメラの映像などを投稿する事が可能です。
まとめ
Raspberry Piのカメラを使うと、様々な事ができるようになります。
WEBアプリを作成するPHPからPythonを呼び出せば、カメラの向きをコントロールしたりする事も可能になります。
次の投稿では、より高度な制御を組み込んでいきます。