vue.jsで画像中にバウンディングボックスを表示させてみる


はじめに

機械学習関連で検出や認識などをしていると、下図みたいに画像中の結果部分を強調表示したくなるときがありました。今回は、デモサイトの開発にvue.jsを利用していたので、コンポーネントとして実装してみました。

やり方

調べてみると、いろんなやり方があるようで

  • SVG
  • Canvas
  • 外部のサーバで処理して結果を受け取る
  • etc...

試してみた結果、vueのテンプレート操作と相性が良かったSVGを使うことにしました。

コンポーネント内での処理

至って簡単。

svg要素の中に

  1. imageタグで画像を描画
  2. コンポーネントの引数として受け取った座標(左上を原点とした場合の割合)の個数分だけv-for で繰り返し、rectタグ(バウンディングボックス)を描画

以上

コンポーネント内のテンプレート部分

<svg v-if="imgsize" :viewBox="'0 0 ' + imgsize.width + ' ' + imgsize.height">
    <image :xlink:href="src" width="100%" height="100%"/>
    <rect
      v-for="(bb, i) in bbs" :key="'bb' + i"
      :x="bb.left * imgsize.width || '0'" :y="bb.top * imgsize.height || '0'" :width="bb.width * imgsize.width || '0'" :height="bb.height * imgsize.height || '0'"
      fill="none" :stroke="bbcolor || '#EF5350'" :stroke-width="bbstroke || '2'" vector-effect="non-scaling-stroke" shape-rendering="crispEdges"/>
</svg>

結果

こんな感じ

See the Pen vue-boundingbox by icchi (@icchi) on CodePen.

まとめ

Reactと違い、vueだとSVG内要素の繰り返し処理など、非常に簡単に実装できました。動作も特にもっさり感はなくいい感じです。

もし需要があるなら、npmに公開しようかな...