こんにちは! けい(Twitter)です。
今回は、ラズパイでカメラから取得した画像をマトリックスLEDにリアルタイムで映す方法についてまとめていきたいと思います。
なんとなくやってみたら、Twitterでプチバズりしてある程度の需要はあるのかな?と思っているので、いつもより少し気合が入っています(笑)。
目次
必要な物
ラズパイ
webカメラ
ラズパイ用のカメラモジュールでも出来ますが、接続するのが面倒だったのでwebカメラで動作させました。
マトリックスLED
aliexpressで一枚1600円ものを買いました。リンク
マトリックスLEDは中国サイトで買うのが品ぞろえもコスパもいいと思います。
スイッチング電源
マトリックスLEDの消費電力が大きいので、5Vを出力できるスイッチング電源を用意しました。
スイッチング電源入力端子
スイッチング電源にコンセントからAC100Vを供給するためのコードです。
配線 & ライブラリのインストール
ここら辺は前回の記事と全く同じ内容なので、そちらを参照してください。
今回はマトリックスLEDを1枚だけ使います。
配線でのトラブルが起きることが多いので、前回の記事のデモが動作するのを確認してからこの先を進むと良いと思います。
また、前回の記事でライブラリをダウンロードした前提で進めていきますので、そちらもお願いします。
pythonライブラリのインストール
マトリックスLEDの制御ライブラリ
前回は「rpi-rgb-led-matrix」というライブラリを用いて、コマンドでマトリックスLEDを制御しました。
しかし、今回はカメラの画像の情報を使いたいのでPythonでプログラムを書きます。
(本当はシェルスクリプトで書きたかったけど、リアルタイム性に欠けたのでPythonにしました)
それでは、Pythonライブラリのインストール作業を行います。
下記コマンドをターミナルで実行します。(rpi-rgb-matrixのダウンロード前提)
sudo apt-get update && sudo apt-get install python3-dev python3-pillow -y
cd ~/rpi-rgb-led-matrix/bindings/python
make build-python PYTHON=$(which python3)
sudo make install-python PYTHON=$(which python3)
OpenCVのインストール
Pythonで画像を取り扱うにあたって、私が愛用しているOpenCVを使います。
インストール作業は少し面倒ですが、OpenCVは便利なのでぜひ使っていただきたいです。
まずはアップデートとpipのアップグレードを行います。
sudo apt update
sudo apt upgrade
sudo pip install --upgrade pip
依存ライブラリのインストールを行います。
sudo apt install libavutil56 libcairo-gobject2 libgtk-3-0 libqtgui4 libpango-1.0-0 libqtcore4 libavcodec58 libcairo2 libswscale5 libtiff5 libqt4-test libatk1.0-0 libavformat58 libgdk-pixbuf2.0-0 libilmbase23 libjasper1 libopenexr23 libpangocairo-1.0-0 libwebp6
opencv-pythonのインストールを行います。
sudo pip3 install opencv-python
これで通常インストールが成功すると思いますが、importするときにエラーになることがあるようです。
プログラム
マトリックスLEDにカメラ画像をリアルタイムで映すプログラムです。
import numpy as np
import cv2
from rgbmatrix import RGBMatrix, RGBMatrixOptions
from PIL import Image
import time
cap = cv2.VideoCapture(-1)
## matrixLED オプション設定
options = RGBMatrixOptions()
options.rows = 32
options.cols = 64
options.chain_length = 1
options.parallel = 1
# options.hardware_mapping = 'regular' # If you have an Adafruit HAT: 'adafruit-hat'
options.disable_hardware_pulsing = 1
options.gpio_slowdown = 5
# options.brightness = 70
# options.limit_refresh_rate_hz = 200
# options.show_refresh_rate = 50
# options.pwm_lsb_nanoseconds = 350
matrix = RGBMatrix(options = options)
# トリミング 設定
x,y = 8, 0
w,h = 32, 64
def cv2pil(image):
''' OpenCV型 -> PIL型 '''
new_image = image.copy()
if new_image.ndim == 2: # モノクロ
pass
elif new_image.shape[2] == 3: # カラー
new_image = new_image[:, :, ::-1]
elif new_image.shape[2] == 4: # 透過
new_image = new_image[:, :, [2, 1, 0, 3]]
new_image = Image.fromarray(new_image)
return new_image
try:
while(True):
ret, frame = cap.read()
height, width, channels = frame.shape[:3]
print('original image : ' + str(width) + 'x' + str(height))
frame2 = cv2.resize(frame, (64,48)) # 縮小 640x480 > 64x48
frame3 = frame2[x:x+w, y:y+h] # トリミング 64x48 > 64x32
image = cv2pil(frame3)
matrix.SetImage(image.convert('RGB'))
except KeyboardInterrupt:
cap.release()
プログラム解説
オプション設定(10~21行目)
マトリックスLEDを綺麗に光らせるために重要な項目です。
ここは何度もプログラムを実行してみて、最適なパラメーターを見つけて下さい。
画像のちらつきがある場合は、「options.gpio_slowdown」という項目をいじれば結構改善されました。
どんなオプションがあるかはここから見れます。
画像の縮小&トリミング
画像をマトリックスLEDで表示するためには、マトリックスLEDのピクセル数に合わせる必要があります。
今回私は、64×32のマトリックスLEDを使ったので、取り込んだ画像を最終的にそのサイズに変更する必要があります。
そこでまず取り込んだ画像(640×480)を縮小し、64×48にします。つまり1/10に縮小しています。
次に、これを64×32にトリミングしています。つまり高さを16行分削っています。
これはお使いのwebカメラが取り込む画像サイズによって変わるので、print文で出力された画像サイズを元にプログラムを調整してください。
PIL画像形式への変換
使用しているライブラリがPIL形式での画像が必要なため、29~39行目の関数を使って最終的な画像の形式をPIL形式に変換しています。
個々の部分のプログラムは次のサイトから拝借しました。参考url