LoginSignup
16
14

More than 3 years have passed since last update.

NodeJSで、サーバ上にある画像をPosenetする

Last updated at Posted at 2019-05-25

ブラウザに表示される画像や、PCカメラからブラウザに映る人間の姿を姿勢推定する「TensorflowJS Posenet」。
ブラウザで動くものを、なぜわざわざNodeJSで動作させたいのか、というと、クライアント側の処理負荷を抑えたい、ということがあります。あと、PHPやMySQLなどのWEB環境と連動しやすくしたいこともあります。

まず、Macを使用し、特定のフォルダに置いてある画像で、NodeJSで姿勢推定が出来るか、試してみました。

必要なライブラリなど

すみません、細かい解説は割愛します。

node-canvas

node-canvas を動かすためのライブラリのインストール

$ brew install pkg-config cairo pango libpng jpeg giflib

node-canvasインストール

$ npm install --save canvas botkit

TensorFlowJS NodeJS

npmでインストールします。

$ npm install --save rollup
$ npm install --save @tensorflow/tfjs@^1.1.0
$ npm install --save @tensorflow-models/posenet
$ npm install --save @tensorflow/tfjs-node

GPUの場合
$ npm install --save @tensorflow/tfjs-node-gpu

注意点

1.tfjsではなく、tfjs-nodeを使うこと。

//const tf = require('@tensorflow/tfjs');
const tf = require('@tensorflow/tfjs-node');

2.画像はCanvasに投影後、テンソル型にして、estimateSinglePose()を実行すること。
NodeJSをバッチで走らすとDOMは無いですが、「node-canvas」でCanvasタグをDOMのように扱えます。

var imageScaleFactor = 0.5;
var outputStride = 16;
var flipHorizontal = false;

// モデルのロード
var net = await posenet.load(0.75);

const img = new Image();
img.src = './hoge.jpg';

const canvas = createCanvas(img.width, img.height);
const ctx = canvas.getContext('2d');
ctx.drawImage(img, 0, 0);

// Tensor型に変換
const input = tf.browser.fromPixels(canvas);

// 姿勢JSON取得
const pose = await net.estimateSinglePose(input, imageScaleFactor, flipHorizontal, outputStride);

console.log(pose);

結果

{
  score: 0.8253553825266221,
  keypoints: [
    { score: 0.9589502215385437, part: 'nose', position: [Object] },
    { score: 0.6782095432281494, part: 'leftEye', position: [Object] },
    { score: 0.9743408560752869, part: 'rightEye', position: [Object] },
    { score: 0.3834344744682312, part: 'leftEar', position: [Object] },
    { score: 0.9573087692260742, part: 'rightEar', position: [Object] },
    {
      score: 0.9608330726623535,
      part: 'leftShoulder',
      position: [Object]
    },
    {
      score: 0.970580518245697,
      part: 'rightShoulder',
      position: [Object]
    },
    {
      score: 0.5824703574180603,
      part: 'leftElbow',
      position: [Object]
    },
    {
      score: 0.8478972911834717,
      part: 'rightElbow',
      position: [Object]
    },
    {
      score: 0.4102041721343994,
      part: 'leftWrist',
      position: [Object]
    },
    {
      score: 0.43626463413238525,
      part: 'rightWrist',
      position: [Object]
    },
    { score: 0.9976338148117065, part: 'leftHip', position: [Object] },
    { score: 0.9926899671554565, part: 'rightHip', position: [Object] },
    { score: 0.9901325702667236, part: 'leftKnee', position: [Object] },
    {
      score: 0.9896235466003418,
      part: 'rightKnee',
      position: [Object]
    },
    {
      score: 0.9450682401657104,
      part: 'leftAnkle',
      position: [Object]
    },
    {
      score: 0.9553994536399841,
      part: 'rightAnkle',
      position: [Object]
    }
  ]
}

あとは、この座標に準じて、キーポイントをcanvasに描画して、Canvasごとfs.writeFile()でアウトプットするだけです。

サーバにアップロードされた複数の画像に、姿勢推定ラインが付けられるようになりますね。

ffmpegでmp4スロー動画を1秒1フレームで切り出し、40枚の画像を処理するのに3分ほど。。この辺りはやはりGPUじゃないと厳しいのかな。

こうして生成したキーポイントとボーンの付いた画像から、さらにffmpegでキーポイント・ボーン付き動画を作ることは出来ますね。JSONファイルに書き出しや、canvasでキーポイント・ボーンだけの動画を生成することも可能。サーバ上のTensorFlow・Posenetで、Openposeに引けを取らない仕様に出来そうです。処理速度は早くないと思いますが。。

CentOSやUbuntuでも同じように出来ると思います。

tiger1.jpg
tiger2.jpg

16
14
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
16
14