2023年3月28日火曜日

本書の演習を picamera2 (libcamera) で実行する方法

1. はじめに

Raspberry Pi OS 2021-10-30 からはじまったバージョン Bullseye ではカメラモジュールの利用方法に大きな変更が加えられ、libcamera というライブラリを用いるようになりました。 これは、本書でカメラを用いるプログラムがそのままでは動かなくなる、ということを意味します。

ただし、Bullseye では「Legacy Camera」という、これまでと互換性のあるカメラの利用方法が可能になっています。この Lecgacy Camera を用いれば本書でカメラを用いるプログラムはそのまま動作します。 しかし、2023年10月にリリースされた OS Bookworm では Legacy Camera のサポートは停止されました。

そこで、本ページでは、Legacy Camera に頼らずに最新の OS で本書の演習を実行する方法を解説します。具体的には、libcamera ライブラリを利用する Python モジュールである picamera2 を使ってプログラムを実行します。

本書のサンプルプログラムは picamera の旧バージョンを使って書かれていました。しかし、picamera2 は picamera とは互換性がありませんので、picamera2 用に書き換えられたプログラムをダウンロードして利用することになります。

2. 準備

サポート環境は Bullseye または Bookworm の 32-bit または 64-bit 版の Raspberry Pi OS です。 Bookworm の場合、64-bit 版でないと 10 章の演習を実行できないので注意しましょう。また、Bullseye の場合は、なるべく新しいバージョンを用いましょう。そうしないと、本ページで利用する picamera2 (python3-picamera2) がインストールされていないことがあるからです。

Bullseye の場合、Legacy Camera モードは無効にしておく必要があります。OS インストール直後の状態ではあらかじめ無効になっています。一度有効にしてしまった方は、 ターミナルを開いて以下の手順に従うことで、raspi-config により Legacy Camera モードを無効にしましょう。
  1. 「 sudo raspi-config 」を実行することで raspi-config を起動
  2. キーボードの「↓」キーを2回押し、「Interface Options」を選択してから「Enter」キーを押す
  3. 「I1 Legacy Camera Enable/Disable」があらかじめ選択されているので、「Enter」キーを押す
  4. 「Would you like to enable legacy camera support?」と聞かれるので「→」キーで「いいえ」が選択された状態にし、「Enter」キーを押す
  5. 「Legacy camera support is disabled」と表示されるので、「了解」が選択された状態で「Enter」キーを押す
  6. raspi-configを起動した状態の画面に戻るので、「TAB」キーを二回クリックし、「Finish」を選択した状態で「Enter」キーを押す
  7. 再起動を促されるので、「はい」が選択された状態で「Enter」キーを押す
以上で、Legacy Camera モードが無効になります。

次に、お使いのカメラモジュールのバージョンを把握してください。2023年3月現在、Raspberry Pi のカメラモジュールにはバージョン1から3があり、下図のような外観をしています。
左から、バージョン1(基板が四角)、バージョン2(基板の角が丸く、レンズ周辺が黒)、バージョン3(基板の角が丸く、レンズ周辺が銀)です。基板上にもバージョンの記載がありますね。

後でダウンロードして頂くプログラムでは、このカメラモジュールのバージョンを手動で指定する箇所があります。このバージョンの指定を自動とすると、映像の画質が低くなったり、映像範囲が狭くなったりしてしまうためです。

3. ダウンロードと実行

それでは、picamera2 を利用するプログラムをダウンロードしましょう。

ターミナルを開き、本書のサンプルファイル(「ml-」で始まるファイル)が存在するディレクトリに移動してください。 サンプルファイルをホームディレクトリに展開した方は移動の必要はありません。bluebacksディレクトリに展開した方は下記のコマンドを実行するのでした。
cd bluebacks
なお、本ページで紹介するプログラムは、「ml-」で始まる本書のサンプルファイルと同じ位置にないと動作しませんので注意してください。

次に、下記の3つのコマンドを順に実行して、必要なファイルのダウンロードと展開を行ってください。コマンドはコピー&貼り付けで実行することを推奨します。展開後はダウンロードした圧縮ファイルは不要となるので削除しています。
wget https://github.com/neuralassembly/raspi/raw/master/mlbb-picamera2.zip
unzip mlbb-picamera2.zip
rm mlbb-picamera2.zip
なお、展開されるファイルの名前は既存のサンプルファイルとは異なりますので、サンプルファイルが上書きされることはありません。展開により現れるファイルは下記の通りです。Pythonプログラムのファイル名の末尾が全て「-picamera2.py」で終わっていることに注意してください。さらに、TensorFlow 2 用のファイルには「-tf2-」がついていることにも着目してください。 なお、TensorFlow 2 用の学習済ファイルである ml-digits-cnn-tf2.h5 と ml-hand-cnn-tf2.h5 は既存のファイルが展開時に上書きされることがあるかもしれませんが、上書きして構いません。
ml-08-01-cameracheck-picamera2.py
ml-08-02-binary-picamera2.py
ml-08-04-recognition-picamera2.py
ml-09-01-janken-picamera2.py
ml-09-02-janken-shorten-picamera2.py
ml-10-08-hand-cnn-load-picamera2.py
ml-10-09-janken-deep-picamera2.py
ml-10-09-janken-deep-tf2-picamera2.py
ml-10-10-janken-deep-shorten-picamera2.py
ml-10-10-janken-deep-shorten-tf2-picamera2.py
ml-digits-cnn-tf2.h5
ml-hand-cnn-tf2.h5
さて、これらのPythonプログラムを開くと、全てのファイルの冒頭に、
camver = 1
という行があります。これは、用いるカメラモジュールのバージョンが 1 であることを示しています。お使いのカメラモジュールに応じて、全てのファイルでここの数字を 2 または 3 に変更し、保存して利用してください。

これらのプログラムを実行する際は、この「-picamera2」がついたファイルを実行するようにしてください。 例えば、書籍でサンプルファイル「ml-08-01-cameracheck.py」を実行する箇所があります。その場合、「ml-08-01-cameracheck.py」ではなく「ml-08-01-cameracheck-picamera2.py」を実行するようにする、ということです。

なお、ml-10-09 と ml-10-10 のプログラムには、ファイル名に「-tf2-」がつかないものとついたものの2種類があります。つかないものは本書で用いた keras + theano 用、「-tf2-」がついたものは TensorFlow2 用です。

以上を踏まえ、各プログラムの実行コマンドを以下に列挙しますので、必要に応じてコピーなどしてご活用ください。
python3 ml-08-01-cameracheck-picamera2.py

python3 ml-08-02-binary-picamera2.py

# 以下、ml-08-03 で result.pkl に学習データを保存した場合
python3 ml-08-04-recognition-picamera2.py result.pkl

python3 ml-09-01-janken-picamera2.py result.pkl

python3 ml-09-02-janken-shorten-picamera2.py result.pkl

# 以下、keras + theano の場合
python3 ml-10-08-hand-cnn-load-picamera2.py ml-hand-cnn.h5

python3 ml-10-09-janken-deep-picamera2.py ml-hand-cnn.h5

python3 ml-10-10-janken-deep-shorten-picamera2.py ml-hand-cnn.h5

# 以下、TensorFlow2 の場合
python3 ml-10-08-hand-cnn-load-picamera2.py ml-hand-cnn-tf2.h5

python3 ml-10-09-janken-deep-tf2-picamera2.py ml-hand-cnn-tf2.h5

python3 ml-10-10-janken-deep-shorten-tf2-picamera2.py ml-hand-cnn-tf2.h5
以上、お疲れさまでした。

4 件のコメント:


  1. 金丸様
    いつも読まさせていただいています。

    突然のご連絡失礼いたします。
    ml-08-02-binary-picamera2.pyを実行したところ以下のエラーが出力されました
    TypeError: mode() got an unexpected keyword argument 'keepdims'
    numpy 素人なのでこの対象が全く見当がつかなく生きず待っていますいます。
    対象教えていただけたら助かります。

    また以下のプログラムを実行したところThonnyでは動作に問題なかったのですが、
    python3 ml-08-01-cameracheck-picamera2.py
    以下のエラーが出力されました
    [4:55:50.193321967] [4152] INFO Camera camera_manager.cpp:297 libcamera v0.0.5+83-bde9b04f
    [4:55:50.218179191] [4153] ERROR V4L2 v4l2_device.cpp:353 'imx708': Unable to set controls: Device or resource busy
    [4:55:50.238106151] [4153] INFO RPI vc4.cpp:437 Registered camera /base/soc/i2c0mux/i2c@1/imx708@1a to Unicam device /dev/media2 and ISP device /dev/media1
    [4:55:50.238187650] [4153] INFO RPI pipeline_base.cpp:1101 Using configuration file '/usr/share/libcamera/pipeline/rpi/vc4/rpi_apps.yaml'
    [4:55:50.240114408] [4152] INFO Camera camera.cpp:840 Pipeline handler in use by another process
    Camera __init__ sequence did not complete.
    Traceback (most recent call last):
    File "/usr/lib/python3/dist-packages/picamera2/picamera2.py", line 242, in __init__
    self._open_camera()
    File "/usr/lib/python3/dist-packages/picamera2/picamera2.py", line 446, in _open_camera
    self.camera.acquire()
    RuntimeError: Failed to acquire camera: Device or resource busy

    During handling of the above exception, another exception occurred:

    Traceback (most recent call last):
    File "/home/pi/ml-08-01-cameracheck-picamera2.py", line 8, in
    picam2 = Picamera2()
    File "/usr/lib/python3/dist-packages/picamera2/picamera2.py", line 254, in __init__
    raise RuntimeError("Camera __init__ sequence did not complete.")
    RuntimeError: Camera __init__ sequence did not complete.
    これに関する対象があれば教えていただけると幸いです。
    お手数ですがよろしくお願いします。

    返信削除
    返信
    1. 失礼しました。

      scipyのバージョンが古いとそのエラーが出る、のですが、
      現状、OSのバージョンが bullseye でもそのエラーが出てしまいますね。
      (最新の bookworm だとエラーが出ません)

      どう修正するかは今後検討しますが、
      m = stats.mode(img_label_not_zero, keepdims=False)[0]
      的な行を
      m = stats.mode(img_label_not_zero)[0]
      とすれば、すなわち「, keepdims=False」を削除すれば
      エラーは出ません。

      お手数ですが当面はそのような対応でお願いします。

      削除
    2. もう一つ、「python3 ml-08-01-cameracheck-picamera2.py」の方は、
      「複数のプログラムからカメラを同時に使用しようとしている」
      ことに関するエラーのように見えますので、
      どちらか一つのプログラムからの実行に絞れば問題ないと思います。

      削除
    3. ファイルを更新しましたので、

      rm -f mlbb-picamera2.zip

      wget https://github.com/neuralassembly/raspi/raw/master/mlbb-picamera2.zip

      でファイルをダウンロードし直し、展開して現れたファイルで既存のファイルを上書きすれば、
      エラーが出なくなっていると思います。

      よろしくお願いします。

      削除