Quantcast
Channel: Node.jsタグが付けられた新着記事 - Qiita
Viewing all articles
Browse latest Browse all 9156

SemanticSegmentationを行うnpmパッケージを作ったので使い方を説明してみる

$
0
0

はじめに

先日、大きな画像を分割してsemantic segmentationを行うnpm パッケージを作成したので、使い方の説明を兼ねてデモの作り方を説明してみます。

このパッケージは、スマホなどの性能の限られたデバイス上で精度と応答速度のトレードオフを調整しながらSemanticSegmentationするためのものです。
今回のデモとしては、このようなものを作ります。バーコードを検出してセグメンテーションを行います。

https___qiita-image-store.s3.ap-northeast-1.amazonaws.com_0_365991_425fef2a-7eef-9bc4-21e0-3960a4c8154e.gif

前回のnpmパッケージを作成した際の投稿はこちらです。
https://qiita.com/wok/items/a6445d17724ed700e448

前準備

今回はReactでデモを作成します。
まずは環境構築をしましょう

$ create-react-app demo --typescript

パッケージをインストール

それではvirtual背景のパッケージをインストールします。

$ npm install scalable-semantic-segmentation-js
$ node node_modules/scalable-semantic-segmentation-js/bin/install_worker.js public
file is copied

使用するモデルの準備

次に使用するSemantic Segmentationのモデルを用意します。
このモデルは、[batch, height, width, channels]のshapeのテンソルを入力として想定しています。

$ ls public/WEB_MODEL/300x300_0.10/
group1-shard1of1.bin  model.json

デモのコード

準備ができたら、ソースコードを作成します。
ここでは、重要と思われる部分のみ解説します。ソース全体は下記のリポジトリに置いてあります。

本デモでは、Reactコンポーネントのメンバー変数としてモジュールのクラスのインスタンスを作っておきます。

scalableSS:ScalableSemanticSegmentation=newScalableSemanticSegmentation()

では、componentDidMoutからみて行きます。

componentDidMount(){console.log('Initializing')constinitWorkerPromise=this.initWorker()// <-- (1)if(navigator.mediaDevices&&navigator.mediaDevices.getUserMedia){// <-- (2)constwebCamPromise=navigator.mediaDevices.getUserMedia({audio:false,video:DisplayConstraintOptions[this.state.videoResolution]}).then(stream=>{console.log(this.videoRef)this.videoRef.current!.srcObject=stream;// <-- (3)returnnewPromise((resolve,reject)=>{this.videoRef.current!.onloadedmetadata=()=>{resolve();};});});Promise.all([initWorkerPromise,webCamPromise]).then((res)=>{console.log('Camera and model ready!')}).catch(error=>{console.error(error);});}}

(1)で今回SemanticSegmentationを行うインスタンスをイニシャライズします。このメソッドの内部は後述します。
(2)でビデオデバイスを取得し、(3)でHTMLVideoElementのソースに設定しています。

次に、initWorkerの中身を見ていきます。

asyncinitWorker(){// SemanticSegmentationthis.scalableSS.addInitializedListener(()=>{// <-- (1-1)constprops=this.propsasanythis.setState({initialized:true})this.requestScanBarcode()// <-- (1-2)})this.scalableSS.addMaskPredictedListeners((maskBitmap:ImageBitmap)=>{// <-- (2-1)// 再キャプチャthis.requestScanBarcode()// <-- (2-2)})this.scalableSS.init(AIConfig.SS_MODEL_PATH,AIConfig.SPLIT_WIDTH,AIConfig.SPLIT_HEIGHT,AIConfig.SPLIT_MARGIN)// <-- (3)return}

本メソッドでは、SemanticSegmentationを行うインスタンスをイニシャライズしています。
まず(1-1)で、インスタンス内部で使用するモデルのロードなどの初期化が完了したときのコールバック関数を設定します。
コールバック関数の中では(1-2)バーコードスキャンを行う関数を呼び出しています。
(2-1)は、セグメンテーションが完了したときに呼び出されるコールバック関数を設定しています。
このとき受け取るパラメータがセグメンテーションの結果のビットマップイメージになります。
コールバック関数の中でも(2-2)バーコードスキャンを行う関数を呼び出しています。これにより処理をループさせています。
(3)でインスタンスに使用するモデルの情報と、画像を分割する際に使用するマージン(分割後の隣り合う画像間でオーバラップする領域の割合)を指定します。第1引数がモデルのパス、第2、3引数がモデルで使用する幅と高さ、第4引数がマージンです。

最後に、requestScanBarcodeです。

requestScanBarcode=async()=>{console.log('requestScanBarcode')constvideo=this.videoRef.current!constcontroller=this.controllerCanvasRef.current!controller.width=this.overlayWidthcontroller.height=this.overlayHeightconstcaptureCanvas=captureVideoImageToCanvas(video)<--(1)if(captureCanvas.width===0){captureCanvas.remove()window.requestAnimationFrame(this.requestScanBarcode);return}this.scalableSS.predict(captureCanvas,this.state.colnum,this.state.rownum)<--(2)captureCanvas.remove()}

ここでは、SemanticSegmentationを行う対象となる画像を取得し、SemanticSegmentionを実行しています。
(1)で、SemanticSegmentationの対象となる画像をHTMLVideoElementから取得しています。この画像を(2)の引数としてモジュールのインスタンスに与え、SemanticSegmentationを実行させています。第2,3引数は分割する行数と列数です。

以上で、セグメンテーションを行う処理は完了です。

デバッグ用に、セグメンテーションの様子や、グリッドの情報を表示することもできます。

<Labelbasicsize="tiny"color={this.state.showSS?"red":"grey"}onClick={()=>{constnewValue=!this.state.showSSthis.scalableSS.previewCanvas=newValue?this.workerSSMaskMonitorCanvasRef.current!:nullthis.setState({showSS:newValue})}}>ss</Label>
<Labelbasicsize="tiny"color={this.state.showGrid?"red":"grey"}onClick={()=>{constnewValue=!this.state.showGridthis.scalableSS.girdDrawCanvas=newValue?this.controllerCanvasRef.current!:nullthis.setState({showGrid:!this.state.showGrid})}}>grid</Label>

this.scalableSS.previewCanvasとthis.scalableSS.girdDrawCanvasにそれぞれ描画するHTMLCanvasElementを設定してください。

デモ

https://scalable-ss-demo.herokuapp.com/index.html

ソースコードとnpmパッケージ

本ソースコードは下記のリポジトリに格納してあります。
https://github.com/FLECT-DEV-TEAM/ScalableSemanticSegmentationjs_demo

npmパッケージのページは次のURLになります。
https://www.npmjs.com/package/scalable-semantic-segmentation-js


Viewing all articles
Browse latest Browse all 9156

Trending Articles