「piカメラ付ラズパイ」のBookwormで、Mediapipeのオブジェクト検出

タイトルにあるように、Raspberry Pi OS Bookworm (64bit) の「pi-V2カメラ付ラズパイ4B」で撮影しながら、Mediapipeのオブジェクト検出* を実施します。ただBookwormですが、仮想環境* は使いません。次に、「pi-V2カメラ付ラズパイ4B」にUSBカメラを追加して、2個のカメラで同時に検出を実施します。この時、USBカメラを追加したのに、Raspberry Pi OS Bookwormで、<font color="#ff0000">"wayland"... のWARNメッセージが出なかった</font>ことが特記事項です。

<b>仮想環境* </b>
OS Bookwormは、仮想環境なしではpipでパッケージモジュールのインストールができず、仮想環境が必須です。ゆえに仮想環境構築に失敗した方は、OS Bookwormに、Mediapipeをインストールできません。つまりMediapipeのオブジェクト検出ができないということです。ただ仮想環境なしで、全く不可能という訳ではなく、非推奨ですが、救済措置として ’ --break-system-packages’ というコマンドオプションが用意されています。このコマンドオプションを使えば、仮想環境なしのOS bookworm上に、Mediapipeのインストールが可能です。今回、このコマンドオプション ’ --break-system-packages’ を使います。

<b>Mediapipeのオブジェクト検出* </b>
Mediapipeのオブジェクト検出は、Raspberry_Pi用がgitに用意されているので、セットアップが楽です。さらにMediapipeでは、オブジェクト検出に使う学習済のModelファイルのカスタマイズ（追加学習)* が、初期投資なしのサブスク形式で、手軽に始められることが大きな魅力です。ただし今回はカスタマイズせず、学習済のModelファイルを使った検出だけを実施します。

<b>MediapipeのModelファイルのカスタマイズ（追加学習)* </b>
具体的には、クラウド上のGPUを備えたGoogle Colabで、Mediapipe Model Maker を使います。Google Colabは無料でも使えます。ただし高性能GPUを使いたい場合は、スマホのGB追加オプションの感覚で、月1200円ほどのColab Proがおすすめです。最初に無料で使い方を習得した後、学習用の画像なども本格的に準備して、Colab Proの高性能GPUを使ってModelファイルのカスタマイズ（追加学習）をするというパターンが効率的そうです。

# マイクロSDカードへのRaspberry Pi OS書込み
今回、信頼性の高いクリーンインスト―ルで実施します。30分ほど時間が掛かりますが確実です。まず空の32GBのマイクロSDカードを用意します。使用したものは、CLASS１, UHS1の記載がありました。特別に速いわけではなく汎用品でした。Raspberry Pi オフィシャルより、Raspberry Pi ImagerをPCへダウンロードします。PCにマイクロSDカードを挿して、ダウンロードした「Imager.exe 」をダブルクリックします。Raspberry Pi デバイスは今回Raspberry Pi 4にします。OSはRaspberry Pi FULL OS (64bit) --bookworm-- を選択します。他に無印(standard)とLITE、さらにLegacyのbullseyeなどがあります。ストレージは32GBを選択します（上書きして全部消去されますので、間違わないようにしてください）。「次へ」、... customized setting? で、「いいえ」。... 本当に続けますか？ で、「はい」。マイクロSDカードへの書き込みが始まり、30分前後かかります。

# ラズパイで初期設定
Bookworm OSを書き込んだマイクロSDカードを、ラズパイ4Bに挿して、起動します。初期設定だけは、USBマウス、USBキーボード、HDMIモニターがあると、大変スムーズにいきます。途中、Update Software は必ず「skip」＊ します。進んで、鵜飼の画面が出ると初期設定の終了です。　
＊ntpサーバーが通じていないので時刻の自動設定ができず、Update Softwareでとまるのでskipします。ntpサーバーが通じない原因は、たぶんルーター設定だと思います。ルーター設定を修正していないので。時刻は後で手動で設定します。

# ラズパイでMediapipeのセットアップ
以下、ラズパイ4Bのbookworm(x64)上に、「仮想環境無し」で、オブジェクト検出（ObjectDetection）用のmediapipeをセットアップします。最初に時刻を合わせます。アクセサリー ＞ LXTerminal で、
```
～ $  sudo date --set='2025/04/21 20:55:30'
```
次に以下を続けて実施します。
```
～ $  pip install mediapipe --break-system-packages
～ $  pip install opencv-python --break-system-packages
～ $  sudo python -m pip install --upgrade pip --break-system-packages
～ $  sudo apt update  ## through
```
ここで、upgradable ... とメッセージが出ますが、次に進みます。
```
～ $  sudo apt install libatlas3-base
～ $  sudo apt install libcap-dev
～ $  git clone https://github.com/googlesamples/mediapipe.git
～ $  cd mediapipe/examples/object_detection/raspberry_pi
```
ダウンロードした home/pi/mediapipe/examples/object_detection/raspberry_pi に、utils.pyというファイルがあります。この中の```visualize```という関数をプログラム中で、importして使います。
```
～ $  python3 -m pip install pip --upgrade --break-system-packages
～ $  python3 -m pip install -r requirements.txt --break-system-packages
～ $  wget -q -O efficientdet.tflite -q https://storage.googleapis.com/mediapipe-models/object_detector/efficientdet_lite0/int8/1/efficientdet_lite0.tflite
```
最後の3行は、setup.shファイルの内容に、--break-system-packages’ を追加しただけです。途中、WARNINGが出ることがありますが、今回はスルーして進みます。
最終行が、今回のオブジェクト検出に使うModelファイルです。CPU用のint8タイプを選択しています。なぜならラズパイのCPUは高性能です。int8タイプのefficientdet_lite0.tfliteをダウンロード後、efficientdet.tfliteへ名前を変更して、home/pi/mediapipe/examples/object_detection/raspberry_piに保存しています。このModelファイルのefficientdet_lite0.tfliteについては、以下のページを見てください。
https://ai.google.dev/edge/mediapipe/solutions/vision/object_detector?hl=ja#efficientdet-lite0_model_recommended
ラズパイのGPUは、普通のディスプレイ表示用の性能です。つまりfloatタイプの計算は並みです。最新GPUを備えたゲーミングPCのように、超高性能GPUではないということです。さらにPCIeのあるラズパイ5でも、最新GPUを増設することはできません。<font color="#eeeeee">~~そこでラズパイ5にはAI-HATが発売されました。しかしAI-HATはHAILO専用です。Mediapipeでは動きません。~~</font>
そこでラズパイ5にはHAILOのAI-HATが発売されました。HAILOはMidiapipeが動ないと思っていましたが、"AI-HAT Mediapipe" で探すと、HAILOコミュニティーで下記のページが見つかりました。Mediapipeが動くそうです。動画では、ほぼリアルタイム検出であり、30fpsはありそうです。まだ自分では検証してないですが。
https://community.hailo.ai/t/accelerating-the-mediapipe-models-with-hailo/3012
PCIeのあるラズパイ5で、Mediapipeの検出用に増設するなら、Googleのdual-edge TPU または Coral TPU です。夢のような動画がYouTubeにありました。ただ、どうやってこれらのTPUを、ラズパイのMediapipe用に動かすのかは、全くわかりません。大きな画像で検出を試みると、極端に検出速度が落ちるので、関心があるのはあるんですが。
https://www.youtube.com/watch?v=oFNKfMCGiqE

以上で、ラズパイでのMediapipeのセットアップは完了しました。

# 検出プログラムの前準備
今回、gitからダウンロードしたhome/pi/mediapipe/examples/object_detection/raspberry_piの<font color="#ff0000">detect.pyは実行しません。</font>ただdetect.pyを参考にします。このdetect.py中のoptionsの中の１つのオプションにresult_callbackがあります。これが複雑な処理をしているようです。そして検出速度が大幅に遅くなっています。このresult_callbackを外します。
https://ai.google.dev/edge/mediapipe/solutions/vision/object_detector/python?hl=ja
このページのoptionsには、base_optionsとmax_resultsとrunning_modeの3個だけでシンプルです。必須なのはbase_optionsとrunning_modeの2個です。max_resultsは無いでも動きましたが、無い場合は100個くらい検出して、画像が検出枠で埋め尽くされます。max_results=5とします。また確率の低い0.1前後の意味不明な検出枠が、出ないようにscore_threshold=0.3も追加しました。
optionsのbase_optionsは、オブジェクト検出に使うmodelファイルへのパスです。先ほどダウンロード保存した、home/pi/mediapipe/examples/object_detection/raspberry_piフォルダーのefficientdet.tfliteファイルを指定します。

ここからが、少し複雑というか、連動してセットでの変更が必要なため、数回試行錯誤しました。optionsのresult_callbackを外すと、「result_callbackとrunning_modeのLIVE_STREAMがセットになっている」というエラーが出ます。ゆえにresult_callbackを外した時、連続的なカメラ画像の場合、running_modeはVIDEOしかありません。次にresult_callbackを外して、running_modeをVIDEOへ変更すると、今度は「detect_asyncは使えない」というエラーが出ます。次ページより、detect_asyncを、detect_for_videoへ変えます。
https://ai.google.dev/edge/api/mediapipe/python/mp/tasks/vision/ObjectDetector#detect_for_video
https://ai.google.dev/edge/mediapipe/solutions/vision/object_detector/python?hl=ja
結局、連続的なカメラ画像でresult_callbackを外すと、running_modeはLIVE_STREAM→VIDEO、そしてdetect_async→detect_for_video、という組合せが1択です。

そして以下のdetect_video_v-rpi.pyになります。ここではpi-V2カメラ用にPicamera2から画像を取り込んでいます。

# 「pi-V2カメラ付ラズパイ4B」
<b>detect_video_v-rpi.py</b>
ここではRaspberry Pi OS Bookworm (64bit) の「pi-V2カメラ付ラズパイ4B」で撮影しながら、Mediapipeのオブジェクト検出を実施します。V2カメラをラズパイ4Bに挿します。この時、usbカメラは外しておきます。そしてラズパイを起動します。home/pi/mediapipe/examples/object_detection/raspberry_piに、以下のコードdetect_video_v-rpi.pyを置きます。
Thonnyで、このdetect_video_v-rpi.pyをLoadします。そしてRunで実行します。
```python:detect_video_v-rpi.py
import sys
import time
import cv2
import numpy as np
from picamera2 import Picamera2
from libcamera import controls  ## V3
 
## ObjectDetector
import mediapipe as mp
from mediapipe.tasks import python
from mediapipe.tasks.python import vision
from utils import visualize

model_path = 'efficientdet.tflite'   ## efficientdet_lite0.tflite (int8)
BaseOptions = mp.tasks.BaseOptions
ObjectDetector = mp.tasks.vision.ObjectDetector
ObjectDetectorOptions = mp.tasks.vision.ObjectDetectorOptions
VisionRunningMode = mp.tasks.vision.RunningMode
options = ObjectDetectorOptions(
                    base_options=BaseOptions(model_asset_path=model_path),
                    running_mode=VisionRunningMode.VIDEO, 
                    max_results=5,
                    score_threshold=0.3)
detector = ObjectDetector.create_from_options(options)
 
## V2-camera-alone
picam2 = Picamera2(0)
picam2.configure(picam2.create_preview_configuration(main={"format": 'XRGB8888', "size": (640, 480)}))
picam2.start()
#picam2.set_controls({"AfMode": controls.AfModeEnum.Continuous}) ## V3
    
start_time = time.time()
while True:
    image = picam2.capture_array()
    rgb_image = cv2.cvtColor(image, cv2.COLOR_BGR2RGB)
    bgr_image = cv2.cvtColor(rgb_image, cv2.COLOR_RGB2BGR)
    image_timestamp_s  = time.time() - start_time
    image_timestamp_ms = int(image_timestamp_s * 1000)
    mp_image = mp.Image(image_format=mp.ImageFormat.SRGB, data=bgr_image)
    detection_result = detector.detect_for_video(mp_image, int(image_timestamp_ms))
 
    visual_image = visualize(np.array(bgr_image).astype(np.uint8), detection_result)
 
    cv2.imshow('Visual Image', visual_image)
    if cv2.waitKey(1) == 27:   ## Esc key
        break
 
detector.close()
picam2.stop()
cv2.destroyAllWindows()
 
"""
Error in cpuinfo: prctl(PR_SVE_GET_VL) failed
INFO: Created TensorFlow Lite XNNPACK delegate for CPU.
[0:05:13.738271071] [1941]  INFO Camera camera_manager.cpp:327 libcamera v0.4.0+53-29156679
[0:05:13.776837293] [1971]  WARN RPiSdn sdn.cpp:40 Using legacy SDN tuning - please consider moving SDN inside rpi.denoise
[0:05:13.781363052] [1971]  INFO RPI vc4.cpp:447 Registered camera /base/soc/i2c0mux/i2c@1/imx219@10 to Unicam device /dev/media1 and ISP device /dev/media2
[0:05:13.781531997] [1971]  INFO RPI pipeline_base.cpp:1121 Using configuration file '/usr/share/libcamera/pipeline/rpi/vc4/rpi_apps.yaml'
[0:05:13.793949701] [1941]  INFO Camera camera.cpp:1202 configuring streams: (0) 640x480-XRGB8888 (1) 640x480-SBGGR10_CSI2P
[0:05:13.794479812] [1971]  INFO RPI vc4.cpp:622 Sensor: /base/soc/i2c0mux/i2c@1/imx219@10 - Selected sensor format: 640x480-SBGGR10_1X10 - Selected unicam format: 640x480-pBAA
"""
```
次のようなメッセージが出ます。

<font color="#ff0000">Error in cpuinfo: prctl(PR_SVE_GET_VL) failed</font>
<font color="#ff0000">INFO: Created TensorFlow Lite XNNPACK delegate for CPU.</font>

これはmediapipeが出したようです。SVEはラズパイ4Bにはハードウェアー的に存在しないので回避不可。SVEはラズパイ５からです。このErrorを消したい場合、ラズパイ5へ変えるしか、方法はありません。TensorFlow Liteは、代替でCPUを使っているようです。これらはスルーして、5秒ほど待ちます。画像が出て、検出します。画像のオブジェクト検出に、遅れはありません。ほぼリアルタイムで検出します。ただ画像表示には1秒ほどの遅延があります。スローモーションで5fps前後です。同時に、次の追加メッセージも出ます。
<font color="#0099ff">[0:05:13.738271071] [1941]  INFO Camera camera_manager.cpp:327 libcamera v0.4.0+53-29156679</font>
<font color="#ff6666">[0:05:13.776837293] [1971]  WARN RPiSdn sdn.cpp:40 Using legacy SDN tuning - please consider moving SDN inside rpi.denoise</font>
<font color="#0099ff">[0:05:13.781363052] [1971]  INFO RPI vc4.cpp:447 Registered camera /base/soc/i2c0mux/i2c@1/imx219@10 to Unicam device /dev/media1 and ISP device /dev/media2</font>
<font color="#0099ff">[0:05:13.781531997] [1971]  INFO RPI pipeline_base.cpp:1121 Using configuration file '/usr/share/libcamera/pipeline/rpi/vc4/rpi_apps.yaml'</font>
<font color="#0099ff">[0:05:13.793949701] [1941]  INFO Camera camera.cpp:1202 configuring streams: (0) 640x480-XRGB8888 (1) 640x480-SBGGR10_CSI2P</font>
<font color="#0099ff">[0:05:13.794479812] [1971]  INFO RPI vc4.cpp:622 Sensor: /base/soc/i2c0mux/i2c@1/imx219@10 - Selected sensor format: 640x480-SBGGR10_1X10 - Selected unicam format: 640x480-pBAA</font>
追加メッセージ中に<font color="#ff6666">WARN</font>が1個だけあります。ラズパイ4B＋V2カメラとbookworm上の新Picamera2の何かが、合っていないためのwarning(警告)だと思います。同じラズパイ4B＋V2カメラで、buster上の旧Picameraの時は、このWARNは見たことがありません。またWARNが原因で、ラズパイ4BやV2カメラが壊れる又は誤動作するという事例は、色々探しましたが無いないようです。どうしても、このWARNを消したいという場合、ラズパイ5＋V3カメラへ変えるしか、方法はないような気がします。

# 「pi-V2カメラ付ラズパイ4B」＋usbカメラ
<b>detect_video_v-rpi_usb.py</b>
ここでは「pi-V2カメラ付ラズパイ4B」にUSBカメラを追加して、2個のカメラで同時に検出を実施します。V2カメラだけをラズパイ4Bに挿して起動します。起動後にusbカメラを挿します。「pi-V2カメラ付ラズパイ4B」＋usbカメラです。Home/pi/mediapipe/examples/object_detection/raspberry_piに、以下のコードdetect_video_v-rpi_usb.pyを置きます。Thonnyで、このdetect_video_v-rpi_usb.pyをLoadします。そしてRunで実行します。
```python:detect_video_v-rpi_usb.py
"""
 ---- Raspberry Pi OS  bookworm 64bit  ----
～ $  sudo date --set='2025/04/21 20:55:30'
 ---- Below, without virtual environment ----
 ---- Mediapipe Object_Detector SetUp ----
～ $  pip install mediapipe --break-system-packages
～ $  pip install opencv-python --break-system-packages
～ $  sudo python -m pip install --upgrade pip --break-system-packages
～ $  sudo apt update
～ $  sudo apt install libatlas3-base
～ $  sudo apt install libcap-dev
～ $  git clone https://github.com/googlesamples/mediapipe.git
～ $  cd mediapipe/examples/object_detection/raspberry_pi
～ $  python3 -m pip install pip --upgrade --break-system-packages
～ $  python3 -m pip install -r requirements.txt --break-system-packages
～ $  wget -q -O efficientdet.tflite -q https://storage.googleapis.com/mediapipe-models/object_detector/efficientdet_lite0/int8/1/efficientdet_lite0.tflite

 put this code in home/pi/mediapipe/examples/object_detection/raspberry_pi
 Start Raspberry Pi with pi-V2 camera.  After starting, insert USB camera.  And Run this code on Thonny and wait for 5 sec.
"""

import sys
import time
from multiprocessing import Manager, Value, Process
import cv2 as cv
import numpy as np
from picamera2 import Picamera2
from libcamera import controls  ## V3 camera

import mediapipe as mp
from mediapipe.tasks import python
from mediapipe.tasks.python import vision
"""
 not LIVE_STREAM but VIDEO
   https://ai.google.dev/edge/api/mediapipe/python/mp/tasks/vision/ObjectDetector
   https://ai.google.dev/edge/mediapipe/solutions/vision/object_detector/python?hl=ja
 create_from_options
   https://github.com/google-ai-edge/mediapipe/blob/master/mediapipe/tasks/python/vision/object_detector.py#L180-L241
 detect_for_video
   https://github.com/google-ai-edge/mediapipe/blob/master/mediapipe/tasks/python/vision/object_detector.py#L289-L338
 mp.tasks.vision.ObjectDetectorOptions
   https://ai.google.dev/edge/api/mediapipe/python/mp/tasks/vision/ObjectDetectorOptions
   https://github.com/google-ai-edge/mediapipe/blob/master/mediapipe/tasks/python/vision/object_detector.py#L52-L107
 refer
   https://ai.google.dev/edge/mediapipe/solutions/vision/pose_landmarker/python?hl=ja
   https://developers.googleblog.com/ja/mediapipe-for-raspberry-pi-and-ios/
   https://ai.google.dev/edge/mediapipe/solutions/tasks?hl=ja
"""

from utils import visualize
model_path = 'efficientdet.tflite'   ## efficientdet_lite0.tflite (int8)
"""
   https://github.com/google-ai-edge/mediapipe-samples/tree/main/examples/object_detection/raspberry_pi
   https://ai.google.dev/edge/mediapipe/solutions/vision/object_detector?hl=ja#efficientdet-lite0_model_recommended
   https://ai.google.dev/edge/mediapipe/solutions/customization/object_detector
   https://colab.research.google.com/github/googlesamples/mediapipe/blob/main/examples/customization/object_detector.ipynb
"""


def process1(mg_pvalue_0, mg_plist_0):
    ## V2 camera
    picam0 = Picamera2(0)
    picam0.configure(picam0.create_preview_configuration(main={"format": 'XRGB8888', "size": (640, 480)}))
    picam0.start()
    #picam0.set_controls({"AfMode": controls.AfModeEnum.Continuous}) ## V3 camera auto focus

    ## ObjectDetector
    BaseOptions = mp.tasks.BaseOptions
    ObjectDetector = mp.tasks.vision.ObjectDetector
    ObjectDetectorOptions = mp.tasks.vision.ObjectDetectorOptions
    VisionRunningMode = mp.tasks.vision.RunningMode
    options = ObjectDetectorOptions(
                        base_options=BaseOptions(model_asset_path=model_path),
                        running_mode=VisionRunningMode.VIDEO,
                        max_results=5,
                        score_threshold=0.3)
    detector = ObjectDetector.create_from_options(options)
    
    start_time = time.time()
    
    while True:
        image = picam0.capture_array()
        rgb_image = cv.cvtColor(image, cv.COLOR_BGR2RGB)
        bgr_image = cv.cvtColor(rgb_image, cv.COLOR_RGB2BGR)
        image_timestamp_s  = time.time() - start_time
        image_timestamp_ms = int(image_timestamp_s * 1000)
        mp_image = mp.Image(image_format=mp.ImageFormat.SRGB, data=bgr_image)
        detection_result = detector.detect_for_video(mp_image, int(image_timestamp_ms))

        visual_image = visualize(np.array(bgr_image).astype(np.uint8), detection_result)

        cv.imshow('V2 Visual Image', visual_image)
        if cv.waitKey(1) == 27:    ## Esc key
            break

    detector.close()
    picam0.stop()
    cv.destroyAllWindows()


def process2(mg_pvalue_0, mg_plist_0):
    ## USB camera
    cap1 = cv.VideoCapture(1)  ## $ ls -l /dev/video*   video0,1,2
    #cap1 = cv.VideoCapture(2)  ## $ ls -l /dev/video*   video0,1,2,3
    cap1.set(cv.CAP_PROP_FRAME_WIDTH, 640)
    cap1.set(cv.CAP_PROP_FRAME_HEIGHT, 480)

    ## ObjectDetector
    BaseOptions = mp.tasks.BaseOptions
    ObjectDetector = mp.tasks.vision.ObjectDetector
    ObjectDetectorOptions = mp.tasks.vision.ObjectDetectorOptions
    VisionRunningMode = mp.tasks.vision.RunningMode
    options = ObjectDetectorOptions(
                        base_options=BaseOptions(model_asset_path=model_path),
                        running_mode=VisionRunningMode.VIDEO,
                        max_results=5,
                        score_threshold=0.3)
    detector = ObjectDetector.create_from_options(options)
    
    success, image = cap1.read()
    if not success:
        sys.exit('ERROR: Unable to read from webcam.')
    
    while success:
        image_timestamp_ms = cap1.get(cv.CAP_PROP_POS_MSEC)
        mp_image = mp.Image(image_format=mp.ImageFormat.SRGB, data=image)
        detection_result = detector.detect_for_video(mp_image, int(image_timestamp_ms))
    
        visual_image = visualize(np.array(image).astype(np.uint8), detection_result)
    
        cv.imshow('USB Visual Image', visual_image)
        if cv.waitKey(1) == 27:    ## Esc key
            break
    
        success, image = cap1.read()
    
    detector.close()
    cap1.release()
    cv.destroyAllWindows()


if __name__ == "__main__":

    ## copied from Manager of Server process in multiprocessing  (Python)
    with Manager() as manager:

        mg_pvalue_0 = manager.Value('i', 0)
        mg_pvalue_0.value  = 0

        mg_plist_0  =  manager.list()

        process1 = Process(target=process1, args=[mg_pvalue_0, mg_plist_0])
        process2 = Process(target=process2, args=[mg_pvalue_0, mg_plist_0])

        process1.start()
        process2.start()

        process1.join()
        process2.join()

"""
[0:09:21.817338256] [1932]  INFO Camera camera_manager.cpp:327 libcamera v0.4.0+53-29156679
[0:09:21.854093737] [1936]  WARN RPiSdn sdn.cpp:40 Using legacy SDN tuning - please consider moving SDN inside rpi.denoise
[0:09:21.857038848] [1936]  INFO RPI vc4.cpp:447 Registered camera /base/soc/i2c0mux/i2c@1/imx219@10 to Unicam device /dev/media1 and ISP device /dev/media2
[0:09:21.857187996] [1936]  INFO RPI pipeline_base.cpp:1121 Using configuration file '/usr/share/libcamera/pipeline/rpi/vc4/rpi_apps.yaml'
[0:09:21.964510200] [1932]  INFO Camera camera.cpp:1202 configuring streams: (0) 640x480-XRGB8888 (1) 640x480-SBGGR10_CSI2P
[0:09:21.965130311] [1936]  INFO RPI vc4.cpp:622 Sensor: /base/soc/i2c0mux/i2c@1/imx219@10 - Selected sensor format: 640x480-SBGGR10_1X10 - Selected unicam format: 640x480-pBAA
Error in cpuinfo: prctl(PR_SVE_GET_VL) failed
Error in cpuinfo: prctl(PR_SVE_GET_VL) failed
INFO: Created TensorFlow Lite XNNPACK delegate for CPU.
INFO: Created TensorFlow Lite XNNPACK delegate for CPU.
"""
```
メッセージは、usbカメラが増えても、pi-V2カメラ単独（detect_video_v-rpi.py）の時と同じです。また今回のようにpi-V2カメラが共存して動作(撮影)している時、Raspberry Pi OS Bookworm上のusbカメラ特有の <font color="#ff0000">"wayland"... のWARNメッセージは出ませんでした。</font>言い忘れていましたが、usbカメラは、Logicool C310nを使っています。

またmultiprocessing部分は、PythonのmultiprocessingのServerプロセスのManager を、ほぼ全コピーして使っています。速度的には、pi-V2カメラ＋usbカメラ(detect_video_v-rpi_usb.py)でも、pi-V2カメラ単独（detect_video_v-rpi.py）の時と、ほぼ同じです。別コアで動いていますから。

一方、ServerプロセスのManagerのプロキシlistとvalueは、今回のプログラム中では、設定はしていますが全く使っていません。ゆえに、以下のページを参考にさせてもらって、pi-V2カメラ＋usbカメラの小画像を、ほぼリアルタイムのストリーミングで、参照・比較するプログラムも、次に計画しています。ただし外には発表しないと思います。
https://qiita.com/like_ndarray/items/b6accb010bde24c477d3
https://qiita.com/like_ndarray/items/d39dbde96d5cdc81421d

# 追伸： "wayland" について
以下のページを参考にさせていただきました。$ sudo raspi-configで、[Advanced Options]、[Wayland]で、3個「X11」,「Wayfire」,「Labwc」あります。ここでデフォルト「Labwc」から「x11」へ変更し、再起動します。これにより、Webカメラ単独でも、"wayland"... のWARNメッセージは出なくなりました。さらに「シャットダウンがメニューから出来ずに、ターミナルからシャットダウンしていました」が、これも改善しました。2025APRのBookwormは、参考ページと逆の症状でした。また今回試行した上述の2個のプログラム detect_video_v-rpi.py と detect_video_v-rpi_usb.py も、変わらず動きました。
https://qiita.com/craftandcoffee/items/62515905cfe797b9d1ba
https://qiita.com/mao172/items/4014ae9d8e1252ddde86

変更途中の小さなトラブルとして、いつもRealVCNを使っていますが、「Labwc」→「X11」の設定変更で、VNC画面が灰色になりました。以下のページを参考に、VNCは回復しました。
https://qiita.com/konchi_konnection/items/c8e2258f0a7efb49302f
https://www.indoorcorgielec.com/products/

こちらは、サーボモーター・ステッパーモーターのHATの方だったので、いろいろ見ていると、次のようなページもありました。前に少しやったことがあるので、自分でも作れるかもしれないかと思いました。
https://qiita.com/retro_C18_4B/items/6c5b687647e255124cd7

以上、Bookwormでの"wayland"のWARNメッセージはクリアしました。いろいろな方にお世話になりました。ありがとうございました。