2014年11月2日日曜日

Raspberry PiとArduinoで16x32 RGB LEDパネルにカメラモジュールの映像を表示してみた

はじめに

5月頃に秋月で「RGBフルカラードットマトリクスLEDパネル 16x32ドット」を購入し、長いこと放置していたのですが、少し時間ができたので試してみることにしました。

最近ずっと仕事で使っていたRaspberry Piで試すことにします。ただし、Raspberry Piに直接接続するわけではなく、

RaspberryPi―(シリアル通信)→Arduino→RGB LEDパネル

という構成にしました。そうすることで、Adafruitで公開されているArduino用のライブラリを流用することができます。

なお、この構成で始めた後に、やはりAdafruitでRaspberry Pi用のチュートリアルが出てることを知りました。そちらのチュートリアルでは画像ファイルをスクロールする例を取り扱っていますが、本ページでは、それとは異なる構成でRaspberry Piのカメラモジュールの映像をRGB LEDパネルに表示するところまでを試してみます(下図)。


準備

まず、AdafruitのArduino用のチュートリアルを元に、Arduinoで動作することを確かめてください。ArduinoのIDEでFile→Examples→RGBmatrixPanelとたどった時に「16x32」が含まれているサンプルは動作します。

用いるArduinoはチュートリアルにあるようにArduino Unoで良いですが、私は「Arduino Pro Mini 328 5V 16MHz」+「FT232RL搭載小型USB-シリアルアダプタ 5V」の組み合わせを用いました。ソースを少し変更するだけでArduino Megaでもいけるようですが、こちらでは試していません。

C++ & OpenCVの場合

それでは、Raspberry Piでの準備に入っていきます。Raspberry Piのカメラモジュールの映像を取得し、それをRGB LEDパネルに表示することを目指しますが、そのためにC++とOpenCVの組み合わせを用いることにします。

最初はPythonと画像処理ライブラリのPillowの組み合わせで試していたのですが、思った速度が出なかったので、C++とOpenCVの組み合わせに切り替えました。Python+Pillow版についてはページ末尾にメモを残しますので、興味のある方はどうぞ。

さて、Raspberry Pi、Arduino、RGB LEDパネルを下記のように接続しておきます。この場合、Arduinoの電源はRaspberry PiのUSBから供給されます。



さらに、Raspberry Piではカメラモジュールを使えるようにしておきましょう。「sudo raspi-config」で設定を起動し、「5. Enable Camera」→「Enable」とたどれば良いのでした。

次に、Raspberry PiでOpenCV、および後に必要なcmakeをインストールします。

sudo apt-get update
sudo apt-get install libopencv-dev cmake

次に、このRaspberry Piのカメラモジュールに対してOpenCVを用いることができるよう、「RaspiCam : C++ API for using Raspberry camera with/without OpenCv」をインストールします。まず、SourceForgeからraspicam-0.1.1.zip (129.5 kB)をダウンロードし、下記のコマンドでインストールします。

unzip raspicam-0.1.1.zip
cd raspicam-0.1.1
mkdir build
cd build
cmake ..
make
sudo make install
sudo ldconfig

このRaspiCamを用いると、Raspberry Piのカメラモジュールで取得した画像に対してOpenCVを利用できるので良さそうです。私は普段OpenCVを使っているわけではなく、RaspiCamも今回初めて触ったので、「良さそう」という程度しか言えないのですが。

次に、RGB LEDパネル用に私が用意したファイルを準備します。

cd
git clone https://github.com/neuralassembly/raspi_16x32RGBLED
cd raspi_16x32RGBLED
make

makeを実行した後、しばらく待つとビルドが完了します。画像ファイル表示用のimage2LEDmatrix、カメラモジュール表示用のcamera2LEDmatrixの2つの実行ファイルができています。 

さらに、Arduino用のserial2LEDmatrix.inoというC言語ファイルが存在します。このserial2LEDmatrix.inoをWindowsなどであらかじめArduinoに書き込んでおきましょう。 

このスケッチは、下図のように16x32x3バイトの階調(各階調は0~Fで表示)をシリアル通信で受け取り、「.」(ピリオド)を受け取ったタイミングでLEDパネルの内容を更新するように記述されています。



以下、image2LEDmatrixとcamera2LEDmatrixの使用法を解説してきます。

画像ファイルの表示 

image2LEDmatrixはSDカード上の画像をRGB LEDパネルに表示するプログラムです。練習兼動作検証用に書きました。

任意サイズの画像を与えることができます。画像の形式は、JPEGやPNGなど、OpenCVが読み込みに対応しているものです。動作モードは下記の2モードあります。

./image2LEDmatrix filename 0

末尾の0は省略することができます。こちらは下図のように画像の全体をスケーリングして表示します。なお、このページの画像は、見やすくするために全てRGB LEDパネルに紙をかぶせて撮影しています。


一方、下記の用に末尾に1をつけて起動すると、下図のように画像の左右または上下を捨て、なるべく画像を大きく表示します。

./image2LEDmatrix filename 1


Raspberry Piのカメラモジュールの映像の表示

カメラモジュールの映像を表示するには、下記のコマンドを実行します。

./camera2LEDmatrix

すると、下図のようにカメラモジュールの映像がRGB LEDパネルに表示されます。真面目に計測していませんが、体感で5fps以上は出ているのではないかと思います。

なお、フレームレートが低いのは、動作の安定化のためにwhileループ内でusleep関数によるウェイトを入れているためです。RaspiCam自体は約30fpsで映像を取得する能力がありますのでご注意ください。


やってみるとわかりますが(いや、やる前にわかるか)、解像度があまりにも小さいことと、LEDが明るすぎることとがあいまって、何が映っているかわからないことが多く、ちょっと厳しいです。

普通に周囲の映像を映すと、ほとんどのLEDがかなりの輝度で輝くので、1.0A以上の電流がパネルに流れてしまいます。

そのため、使いこなすには何らかの画像処理が必要そうです。せっかくOpenCVを使っているので、エッジ抽出、ビット反転、時間差分などを試したのですが、解像度の小ささから、何が起こっているのかわからず、イマイチでした。

何か面白い応用があれば、お知らせ頂ければ幸いです。

(おまけ)Pythonの場合

上で、C++とOpenCVでの例を紹介しましたが、その前にはPython + Pillowで試していました。この方法にはいくつか欠点があったため途中でやめてしまったのですが、メモとして記録を残しておきます。

準備

まず回路ですが、Python用いてArduinoとシリアル通信する場合は、こちらのstackoverflowにかかれているように、ArduinoのRESETとGNDの間に220μF程度のコンデンサを挟む必要があります。ただし、このコンデンサはスケッチ書き込み時は外してください。
(追記:すいません、コンデンサなしでも問題なく動くかもしれません。追試の必要あり)


次に、Raspberry Piでpipとpython-devとlibjpeg8-devをインストールします。

sudo apt-get update
sudo apt-get install python-pip python-dev libjpeg8-dev

次に、Pillow をインストールします。

sudo pip install pillow

以上の準備のもと、次に、RGB LEDパネル用に私が用意したファイルを準備します。

git clone https://github.com/neuralassembly/raspi_16x32RGBLED_Python

raspi_16x32RGBLED_Pythonの中に、画像ファイル表示用のimage2LEDmatrix.pyとカメラモジュールの映像表示用のcamera2LEDmatrix.pyとが入っています。

これらを用いるのは、C++版でも用いたserial2LEDmatrix.inoをArduinoに書き込んでおいてください。これは https://github.com/neuralassembly/raspi_16x32RGBLED に含まれています。

画像ファイルの表示

C++版と同様に、画像全体表示

python image2LEDmatrix.py filename 0

および、画像の切り出し表示

python image2LEDmatrix.py filename 1

に対応しています(末尾の0は省略できます)。画像ファイルのサイズも任意ですが、画像リサイズのアルゴリズム(PIL.Image.NEAREST、PIL.Image.BILINEAR、PIL.Image.BICUBIC、PIL.Image.ANTIALIAS)がイマイチなため、縮小後の画像があまり綺麗に表示されないことがあるのが欠点です(OpenCV版ではINTER_AREAを用いました)。

そのため、Python版ではWindowsのgimpなどで事前に画像を横32x縦16にリサイズしておいた方が良い場合があります。

Raspberry Piのカメラモジュールの映像の表示

カメラモジュールの映像を表示するには、下記のコマンドを用います。この辺りを参考にしました。

python camera2LEDmatrix.py

残念ながら、こちらはでは、2秒に1回程度しか映像が更新されません。そのため、Pythonをあきらめ、C++とOpenCVによる方法に移行したのでした。




「ラズパイ4対応 カラー図解 最新 Raspberry Piで学ぶ電子工作」、「実例で学ぶRaspberry Pi電子工作」、「Raspberry Piではじめる機械学習」を執筆しました。