メインコンテンツまでスキップ

カメラ入力ノード

CameraInput は、libcamera および GStreamer の libcamerasrc を介して公開される MIPI カメラのソースノードです。フレームを run.push(...) ではなく、DevKit カメラスタックから取得する必要がある場合、ソースが所有するグラフの先頭で使用します。

タスクガイドについては、MIPIカメラを使用する を参照してください。

前提条件​

CameraInputを使用する前に、Neatの外でカメラを起動してください。

  • Modalix DevKit の電源を切った状態でカメラを取り付けてください。
  • キャリアボード、カメラベンダー、センサー、ポートに適合する.dtboオーバーレイを選択してください。
  • libcameraがカメラをリストに表示することを確認してください。
  • 要求する予定の正確な format,width,height,framerate を、libcamerasrc がストリーミングできることを確認してください。

camera_name は libcamera のカメラ名です。デフォルトのカメラを使用する場合は、この変数を設定する必要はありません。ボードに複数のカメラが搭載されている場合は、cam -l からカメラ名を取得して設定してください。

クイックスタート​

#include <neat.h>

namespace neat = simaai::neat;

neat::CameraInputOptions opt;
opt.width = 1920;
opt.height = 1080;
opt.framerate_num = 30;
opt.framerate_den = 1;
opt.format = "NV12";
opt.buffer_name = "camera0";
opt.allow_cpu_fallback = true;

neat::Graph graph;
graph.add(neat::nodes::CameraInput(opt));
graph.add(neat::nodes::Output("frames"));

neat::Run run = graph.build();
std::optional<neat::Sample> frame = run.pull(/*timeout_ms=*/5000);

CameraInput がソースを所有しているため、アプリケーションに別のアプリからプッシュされる入力が本当に必要でない限り、公開された Input ノードなしでグラフを構築してください。

APIのインターフェース​

namespace simaai::neat {
struct CameraInputOptions;
class CameraInput;
}

namespace simaai::neat::nodes {
std::shared_ptr<simaai::neat::Node> CameraInput(
simaai::neat::CameraInputOptions opt = {});
std::shared_ptr<simaai::neat::Node> CameraInputWithCaptureBuffers(
simaai::neat::CameraInputOptions opt,
std::uint32_t capture_buffer_count);
}

Python:

opt = pyneat.CameraInputOptions()
node = pyneat.nodes.camera_input(opt, capture_buffer_count=32)

オプション​

フィールドデフォルト値意味
camera_nameを設定解除します。これは、オプションのlibcameraカメラ名であり、通常はcam -lからコピーされます。設定を解除すると、libcameraがデフォルトのカメラを選択します。
width1920ピクセル単位で指定する、要求されるフレームの幅。カメラモードとオーバーレイでサポートされている必要があります。
height1080ピクセル単位で要求されるフレームの高さ。
framerate_num30フレームレートの分子。
framerate_den1フレームレートの分母。0 は 1 に正規化されます。
format"NV12"が要求されました。video/x-raw 形式です。NV12 が推奨されるモデル前処理パスです。
buffer_name"camera":後続のメタデータやモデルのルート名に使用される論理的なバッファ名。
insert_queuetrueアロケーターのネゴシエーションとゼロコピー検証の後に、小さなライブソースキューを挿入します。
leaky_queuetrueキューをダウンストリームで「リーキー」にし、リアルタイムのグラフが、古いバックログよりも新しいフレームを優先するようにします。
queue_depth2。insert_queue が true の場合に、キューに格納できる最大バッファー数。
allow_cpu_fallbackfalsefalse の場合、カメラの DMA-BUF を転送し、コピーが必要なフレームがあれば失敗します。true に設定するのは、Neat のプライベートブリッジがそのようなフレームを CMA DMA-BUF にコピーできるようにする場合のみです。

capture_buffer_count は、CameraInputOptions のフィールドではなく、CameraInputWithCaptureBuffers への引数です。デフォルト値は 0 であり、これによりカメラのパイプライン自身のデフォルトが維持されます。カメラのパイプラインは、その制限を検証します。Neat のプロバイダーは、最大 128 までをサポートします。

入力と出力の契約​

契約項目動作
入力ロールソースノード。このグラフはカメラからフレームを取得します。アプリケーションがこのノードにサンプルを送信することはありません。
出力メディアの種類は、video/x-rawです。
出力形式は、通常 NV12 形式の format です。
メモリコントラクトカメラ自身のDMA-BUFが、コピーなしで下流に転送されます。フォールバックが有効になっている場合、1つのDMA-BUFではないフレームは、後続のCVU/MLAステージのためにCMA DMA-BUFにコピーされます。
確実性を高める要求されたオプションに基づいて静的なヒントを提供します。ランタイムにおける上限のネゴシエーションは、カメラスタックに依存します。

ゼロコピーとフォールバック​

allow_cpu_fallback = false はデフォルト設定であり、厳密なゼロコピーを要求します。カメラは各フレームを自身の DMA-BUF に書き込み、下流のすべてのステージはその同じメモリを読み取ります。Neat はカメラのメモリを所有しないため、libcamerasrc のプロパティは必要ありません。物理的に連続した DMA-BUF であれば、どれも有効な EV74 入力であり、CMA ヒープまたはカメラの連続キャプチャアロケーター(videobuf2_dma_contig)に由来する場合は、Neat の EV74 受け入れチェックがそれを受け入れます。

Neat は、常に独自のカメラブリッジを capsfilter の直後、ライブキューの直前に配置します。ブリッジは、GST_QUERY_ALLOCATION を介してソースに GstVideoMeta を付加するよう要求し、各平面が 1 つの DMA-BUF 内で連続して並んでいるフレームを単一のメモリとして転送します。その際、すべてのコンシューマーが解放するまでカメラのバッファーを保持します。厳密モードでは、この方法で転送できないフレームはパイプラインを失敗させます。フォールバックが有効な場合は、代わりに CMA DMA-BUF にコピーされます。

ダウンストリームのオーナーに基づいて、capture_buffer_count をカメラファクトリに渡します。一時的なエンコーダまたはディープ非同期 ML グラフには 32 個のバッファが必要になる場合があります。低遅延の CV グラフでは、より少ないバッファを使用し、古いフレームを破棄できます。この設定は、ISP 出力/アプリケーションサイクルのみを制御します。カーネルのプライベート CSI-to-ISP RAW トランジットリングを拡張するものではなく、GStreamer の queue_depth ドロップポリシーとは独立しています。Platform 3.0 では libcamerasrc に buffer-count プロパティがないため、そこでは capture_buffer_count を 0 のままにしてください。

ブリッジはカメラ自身のバッファーを転送するため、下流のステージがまだ保持しているフレームごとに、libcamera のキャプチャリングのバッファーが 1 つずつ使用中のままになります(Platform 3.0 の IMX477 で 1080p NV12 の場合は 8 バッファー)。その数だけフレームを保持するグラフは、フレームを破棄するのではなくキャプチャを停止させるため、取り出したフレームは速やかに解放してください。

allow_cpu_fallback = true を明示的に設定して、フレームが、各平面が連続して並んだ 1 つの DMA-BUF ではない場合に、すでに存在するブリッジがコピーできるようにします。ブリッジは、そのような DMA-BUF であるフレームは引き続きそのまま転送します。それ以外の場合は、カメラフレームをプライベートプールの CMA DMA-BUF にコピーし、ダウンストリームステージが期待するメタデータをアタッチします。このプールは、queue_depth によって制限されるのではなく、必要に応じて最大 128 バッファーまで拡張されます。これにより、ダウンストリームのリーキーキューが古いフレームを破棄しても、ブリッジが最初に停止することはありません。

fallback という名前は、ブリッジが OS/libcamera バッファを受け入れることができることを意味します。リサイズ、カラー変換、または正規化を CPU に移動する必要があるわけではありません。これらの操作は、可能な限り、モデル管理された CVU プリプロセスに含めてください。

CameraInput に対して、OsToSima ノードを自分で追加しないでください。アダプテーションは、カメラソースパスに属します。

一般的なグラフの種類​

カメラのフレームを直接取り出す:

CameraInput -> Output

モデルにカメラを移動させてみる:

CameraInput -> model.graph({include_input=false, include_output=true})

モデルのパイプラインの場合、リサイズ、カラー変換、正規化、量子化、およびテッセレーションなどの前処理を、Model::Options::preprocessまたはpyneat.ModelOptions.preprocessを使用して設定することで、これらの処理がモデルによって管理されるCVU(コンピュータービジョンユニット)の経路に留まるようにします。

故障モード​

エラー考えられる原因
build.plugin_missingランタイムプラグインセットに、libcamerasrc または neatcamerabridge が含まれていません。
misconfig.media_caps / not-negotiatedカメラは、要求されたフォーマット、解像度、またはフレームレートをサポートしていません。
misconfig.media_caps / gstreamer.camera_configuration_unsupportedカメラが要求された解像度またはピクセルフォーマットを提供していないため、libcamerasrc のネゴシエーションが失敗しました。サポートされているサイズでキャプチャしてください。モデルグラフではモデルの前処理でサイズを変更し、それ以外のグラフでは VideoScale の後に CapsRaw を使用してください。
厳密なゼロコピーエラーが発生しました。allow_cpu_fallback は false に設定されており、カメラが、各平面が連続して並んだ 1 つの DMA-BUF ではないフレームを渡しました。
プルタイムアウトカメラからフレームが送信されなかった、グラフにバックプレッシャーがかかっている、またはカメラスタックがストリーミングを停止しました。
緑色、紫色、または色味が強いフレームフレーム形式またはモデルのプリプロセスにおけるカラー変換が正しくないか、すでにカメラのISP/libcamera出力に色味が適用されている可能性があります。まず、NV12形式でキャプチャを行い、Neatで検証してください。