2024年11月20日水曜日

TensorFlow.jsによるビデオをソースとした物体検出を実装する

TensorFlow.jsを使ってビデオをソースとした物体検出を実装します。

実装はLearning TensorFlow.jsのChapter 6 Advanced Models and UIで紹介されていますが、実際に試してみるとモデルが無かったり、キャンバスへのバウンディング・ボックスの描画がビデオに重ねて表示されなかったりと、うまくいかない点がありました。結果として、かなり違う実装になっています。

作成したAPEXアプリケーションは以下のように動作します。ボタンDETECTをクリックすると物体認識を開始し、ボタンStopをクリックすると停止します。


APEXアプリケーションにはホーム・ページのみがあり、機能はすべてホーム・ページに実装しています。


静的コンテンツのリージョンを作成し、スマートフォンではリア・カメラ、PCではメイン・カメラをソースとした動画を表示するVIDEO要素をソースHTMLコードに記述します。
<div id="video-container">
<video id="mystery" playsinline autoplay muted>
    <source src="" type="video/mp4">
       Your browser does not support the video tag.
    </source>
</video>
</div>
VIDEO要素の親のDIV要素(ID: video-container)の子ノードとして、検出した物体を囲むバウンディング・ボックスとなるDIV要素を作成します。


VIDEO要素やバウンディング・ボックスの表示は、ページ・プロパティCSSインラインに定義します。
#mystery {
    position: absolute;
    top: 0;
    left: 10%;
    width: 80%;
}

.bounding-box {
    border-color: #0F0;
    position: absolute;
    box-sizing: border-box;
    border-width: 2px;
    border-style: solid;
}

.bounding-box-label {
    color: black;
    background-color: #0F0;
    position: absolute;
    top: 0;
    left: 0;
    font-size: 12px;
    padding: 1px;
}

TensorFlow.js自体やロードしたモデル、Webカメラの状態などを表示するページ・アイテムとしてP1_STATUSを作成します。タイプ表示のみです。


物体検知に関するほとんどの設定は、ページ・プロパティJavaScriptに行います。

ファイルURLに以下を記述します。TensorFlow.jsのバックエンドとしてWebGLとWebGPUをロードしています。iPhone(Safari)ではWebGL、Mac(Chrome)ではWebGPUのバックエンドを使用できました。この他にWasm、CPUがありますが、それらはロードしていません。
https://cdn.jsdelivr.net/npm/@tensorflow/tfjs/dist/tf.min.js
https://cdn.jsdelivr.net/npm/@tensorflow/tfjs-backend-webgl/dist/tf-backend-webgl.min.js
https://cdn.jsdelivr.net/npm/@tensorflow/tfjs-backend-webgpu/dist/tf-backend-webgpu.min.js
https://cdn.jsdelivr.net/npm/@tensorflow-models/coco-ssd/dist/coco-ssd.min.js
物体検知のモデルとしてcoco-ssd.min.jsを読み込んでいます。jsDelivrの以下のページに説明されているように、ポスト処理としてNonMaxSuppressionの処理を含んでいるため、Learning TensorFlow.js(Chapter 6のIoUs and NMSのセクション)で説明されているコーディングは不要になっています。

TensorFlow.jsやモデルを準備するコードは、ページ・ロード時に実行に記述します。

ブラウザでWebGPUが利用可能であれば、WebGPUを使用します。それ以外はWebGLを使用します。WebGLが使えない場合はエラーになります。Coco-SSDのベースとして、軽量なlite_mobilenet_v2を選択しています。



物体検出を行なうファンクションdetectAnimateは、ファンクションおよびグローバル変数の宣言に記述します。



ボタンDETECTをクリックした時に物体検出を開始します。動的アクションで以下のJavaScriptを実行します。

requestAnimationFrame(detectAnimate);


ボタンSTOPを押した時に、物体検出を停止します。以下のJavaScriptを実行します。

cancelAnimationFrame(animationId);


以上でアプリケーションは完成です。アプリケーションを実行すると、記事の先頭のGIF動画のように動作します。

今回作成したAPEXアプリケーションのエクスポートを以下に置きました。
https://github.com/ujnak/apexapps/blob/master/exports/tensorflow-js-video-object-detection.zip

Oracle APEXのアプリケーション作成の参考になれば幸いです。