HumansXドキュメントセンター 公式サイトへ ↗

1.3 Web ブラウザでのカメラ映像表示

サンプルの概要

Web 表示カメラのサンプルは、/app/pydev_demo/09_web_display_camera_sample/ にある Python インターフェースの開発コード例です。オンボードの MIPI カメラでリアルタイム物体検出を行い、WebSocket を通じて検出結果を Web ブラウザに送信してリアルタイム表示する方法を示します。このサンプルでは YOLOv5x 物体検出モデルを使用して MIPI カメラで取得したビデオストリームにリアルタイムで推論を行い、WebSocket プロトコルで画像と検出枠の情報を Web クライアントに送信します。

実行結果の例

実行後、ブラウザで開発ボードの IP アドレスにアクセスすると、Web ページ上でカメラ映像と検出結果をリアルタイムで確認できます。

ハードウェアの準備

ハードウェア接続

  1. RDK 開発ボードを 1 台用意します
  2. 公式対応の MIPI カメラを接続します
  3. LAN ケーブルを開発ボードに接続します
  4. 電源ケーブルを接続します

クイックスタート

コードとボード上の場所

/app/pydev_demo/09_web_display_camera_sample/ に移動すると、Web 表示カメラのサンプルに含まれる以下のファイルを確認できます。

root@ubuntu:/app/pydev_demo/09_web_display_camera_sample# tree
.
├── coco_classes.names
├── mipi_camera_web_yolov5x.py
├── start_nginx.sh
├── webservice
│   ├── client_body_temp
│   ├── conf
│   │   ├── nginx.conf
│   │   ├── ...
│   ├── html
│   │   ├── assets
│   │   ├── index.html
│   │   └── ...
│   ├── logs
│   ├── proxy_temp
│   └── sbin
└── x3_pb2.py

コンパイルと実行

まず Nginx サーバーを起動し、次に Python スクリプトを実行します。

ヒント

IMX477 カメラを使用する場合は、mipi_camera_web.py ファイル内(39 行目付近)で fps=50 に設定する必要があります。

```

```

サンプルディレクトリに移動

cd /app/pydev_demo/09_web_display_camera_sample/

Nginx サーバーを起動

cd webservice/ ./sbin/nginx -p .

(./sbin/nginx に実行権限がない場合は、以下のコマンドを参考に権限を付与してください)

chmod +x ./sbin/nginx

Web カメラのサンプルを実行

サンプルディレクトリに戻る

cd .. python mipi_camera_web_yolov5x.py


実行結果

実行すると、プログラムが Web サービスを起動します。ブラウザで開発ボードの IP アドレスにアクセスすると、リアルタイムのビデオストリームと物体検出結果を確認できます。

ブラウザで http:// 開発ボードの IP にアクセスします。デフォルトは http://192.168.127.10 です。

ブラウザに表示される web Display をクリックすると、リアルタイムのビデオストリームと物体検出結果を確認できます。結果は本ページ冒頭の「実行結果の例」をご参照ください。

詳細説明

サンプルプログラムのパラメータオプション

このサンプルはコマンドライン引数による設定に対応しています。引数を指定しない場合、プログラムはデフォルト値を使用して、同じディレクトリにあるテスト画像を自動的に読み込んで推論を行います。

パラメータ 説明 型 デフォルト値
--model-path BPU 量子化モデルのパス(.bin) str /app/model/basic/yolov5x_672x672_nv12.bin
--priority 推論の優先度(0~255、255 が最高) int 0
--bpu-cores BPU コアのインデックスリスト(例:0 1) int list [0]
--label-file クラスラベルファイルのパス str coco_classes.names
--nms-thres 非最大値抑制の IoU しきい値 float 0.45
--score-thres 検出の信頼度しきい値 float 0.25

ソフトウェアアーキテクチャ

ここでは Web 表示カメラのサンプルのソフトウェアアーキテクチャと処理の流れを紹介し、初期化から Web への送信までの一連の実行過程を説明します。コード全体の構造とデータの流れを理解する助けとなります。

Web 表示カメラのサンプルには、mipi_camera_web.py のソースコードだけでなく、Nginx サーバーと Web 受信側も含まれるため、ソフトウェアアーキテクチャはこれまでのサンプルよりやや多くの要素で構成されています。主な構成要素は以下のとおりです。

  1. MIPI カメラによる取得 - srcampy.Camera() で MIPI カメラを初期化し、ビデオストリームを取得します
  2. 物体検出モデル - YOLOv5x 物体検出モデルを読み込み、ビデオフレームに対してリアルタイムで推論を行います
  3. ビデオエンコード - srcampy.Encoder() でビデオフレームを JPEG エンコードします
  4. WebSocket サービス - WebSocket サーバーを作成し、ビデオフレームと検出結果をリアルタイムで送信します
  5. Web フロントエンド - ブラウザでビデオと検出結果を表示するための HTML ページと JavaScript コードを提供します
  6. Nginx サーバー - 静的ファイルの配信と HTTP プロキシ機能を提供します

API の流れ

ここではサンプルプログラムで使用している主な API を挙げ、各 API の機能、入力パラメータ、戻り値を説明します。コードの実装の詳細や API の呼び出し方を素早く理解する助けとなります。

  1. load_class_names(class_file)

クラス名を読み込みます。入力:クラスファイルのパス。戻り値:クラス名のリスト

  1. srcampy.Camera()

MIPI カメラオブジェクトを作成します

  1. cam.open_cam(pipe_id, video_index, fps, width_list, height_list)

カメラを開きます。入力:チャネル番号、ビデオインデックス、フレームレート、幅のリスト [512, 1920]、高さのリスト [512, 1072]

  1. hbm_runtime.HB_HBMRuntime(model_path)

YOLOv5x モデルを読み込みます。入力:モデルファイルのパス

  1. WebSocketServer(host, port, model_handler, camera_manager, detection_classes)

WebSocket サーバーのインスタンスを作成します。入力:ホストアドレス、ポート番号、モデルハンドラー、カメラマネージャー、クラスリスト

  1. websockets.serve(handler, host, port)

WebSocket サーバーを起動します。入力:ハンドラー関数、ホストアドレス(0.0.0.0)、ポート番号(8080)

  1. cam.get_img(chn, width, height)

カメラの元画像を取得します。入力:チャネル番号(2)、幅(1920)、高さ(1072)。戻り値:NV12 形式の画像データ

  1. split_nv12_bytes(img, width, height)

NV12 画像の Y 成分と UV 成分を分離します。入力:NV12 画像データ、幅(1920)、高さ(1072)。戻り値:Y 成分、UV 成分

  1. resize_nv12_yuv(y, uv, target_w, target_h)

NV12 画像をリサイズします。入力:Y 成分、UV 成分、目標の幅(672)、目標の高さ(672)。戻り値:リサイズ後の Y、UV 成分

  1. model.run(input_tensor)

モデル推論を実行します。入力:前処理済みの入力テンソルの辞書。戻り値:モデル出力の辞書

  1. dequantize_outputs(outputs, output_quants)

結果を逆量子化します。入力:モデル出力の辞書、出力の量子化パラメータ。戻り値:float32 型のデータ

  1. decode_outputs(output_names, fp32_outputs, strides, anchors, classes_num)

YOLO モデルの出力をデコードします。入力:出力名のリスト、逆量子化後の出力、ストライド、アンカー、クラス数(80)。戻り値:予測結果

  1. filter_predictions(predictions, score_threshold)

予測結果をフィルタリングします。入力:予測結果、信頼度しきい値。戻り値:検出枠、信頼度、クラス

  1. NMS(boxes, scores, classes, iou_threshold)

非最大値抑制を行います。入力:検出枠、信頼度、クラス、IoU しきい値。戻り値:保持するインデックス

  1. scale_coords_back(boxes, orig_w, orig_h, model_w, model_h, resize_type)

検出枠を元画像のサイズに合わせます。入力:検出枠、元画像の幅(1920)、元画像の高さ(1072)、モデル入力の幅(672)、モデル入力の高さ(672)、リサイズ方式。戻り値:スケーリング後の検出枠

  1. serialize_message(frame_message, data, detection_classes)

検出結果と画像を Protocol Buffer メッセージにシリアライズします。入力:フレームメッセージオブジェクト、検出結果のリスト、クラス名のリスト。戻り値:シリアライズ後のバイト列

  1. websocket.send(serialized_buf)

クライアントにメッセージを送信します。入力:シリアライズ後のデータ(バイト列)

  1. cam.close_cam()

カメラを閉じます

FAQ

Q: サンプル実行時にポートが使用中と表示される場合は? A: 他のプログラムが 8080 番ポートを使用していないか確認してください。netstat -tlnp コマンドでポートの使用状況を確認できます。

Q: ブラウザからビデオストリームにアクセスできない場合は? A: 開発ボードのネットワーク接続を確認し、ファイアウォールが該当ポートへのアクセスをブロックしていないことを確認してください。

Q: ビデオストリームの遅延が大きい場合は? A: ビデオの解像度やフレームレートを下げるか、より軽量な物体検出モデルを使用してみてください。

Q: Web フロントエンドの画面を変更するには? A: webservice/html/ ディレクトリにある HTML、CSS、JavaScript ファイルを変更することで、画面をカスタマイズできます。

Q: 新しい検出クラスを追加するには? A: get_classes() 関数を変更して新しいクラス名を追加し、モデルを再学習するか、新しいクラスに対応したモデルを使用する必要があります。

Q: ビデオストリームを保存するには? A: コードにビデオ保存の処理を追加できます。例えば OpenCV の VideoWriter クラスを使ってビデオファイルを保存します。