ブラウザ上からのDARKNET(YOLO)による認識ラベル画像出力

apprhythm : 2018-01-24
ブラウザ上からのDarknet(YOLO)による認識ラベル画像出力をやってみた。

 

  • Darknet(YOLO)による認識ラベル付与済み画像を、ブラウザをインターフェイスとして生成したい(以下の画像を参考)
  • 環境としてWindows Subsystem on Linux(WSL)のUbuntuを用いる。ブラウザはChromeとする(ほかのブラウザでも可)

 

 

 

Darknetの導入

  • まずdarknetを導入する。以下のコマンドで導入できる:

git clone https://github.com/pjreddie/darknet

cd darknet

make

  • 次に学習済みモデルをダウンロードする。以下のコマンドでできる:

wget http://pjreddie.com/media/files/yolo.weights

Node.jsの導入

  • サーバとしてjsが必要になるので、まずはNode.jsと、Node.jsのパッケージマネージャであるnpmをインストールする。Ubuntuなら以下のコマンドで導入できる。OSによっては「nodejs」が単に「node」のこともある

sudo apt-get install nodejs npm

  • 次に適当なディレクトリ(フォルダ)を作り、作業ディレクトリとする。このディレクトリに入り、以下のコマンドを実行してnodejsプロジェクトとして初期化する。いくつかのことを尋ねられるが全部そのままEnterでよい

npm init

  • js上のサーバサイドフレームワークであるExpressと、ファイルアップロードを補助するライブラリmulterを導入する。以下のコマンドで導入できる:

npm install express multer –save

サーバとウェブページの作成

  • jsというファイルを作り、以下のコードを貼り付ける。詳しくはコード中のコメントを参照

‘use strict’;

 

const execSync = require(‘child_process’).execSync;

const express = require(‘express’);

 

const multer = require(‘multer’);

const storage = multer.diskStorage({

destination: function (req, file, cb) {

cb(null, ‘./’);

},

filename: function (req, file, cb) {

cb(null, file.originalname);

}

});

const upload = multer({storage: storage});

 

const app = express();

 

app.use(express.static(__dirname));

 

// darknetを導入したディレクトリ。

// 今回はホームディレクトリ直下

const dnDir = ‘~/darknet’;

 

// HTMLを表示

app.get(‘/’, (req, res) => res.sendFile(‘./index.html’));

 

// 画像アップロードをPOSTで受け付け

app.post(‘/’, upload.single(‘input-img’), (req, res) => {

console.log(`[done] Image upload`);

console.log(req.file);

 

// darknetを導入したディレクトリに移動し、

// darknetを実行する。するとpredictions.pngというファイルが出力されるので、

// それをウェブサーバのディレクトリまでコピーしてくる

//

// 注意:この方法だと複数のユーザから同時にアップロードされた場合対応できないので

// 別の方法を考える必要がある。

execSync(`(cd ${dnDir} && ./darknet detect cfg/yolo.cfg yolo.weights ${__dirname}/${req.file.filename} && cp predictions.png ${__dirname}/predictions.png)`);

 

console.log(‘Darknet done.’);

 

// 画像ファイルのパスをJSONで返す

res.type(‘application/json’);

res.send(JSON.stringify({

“path”: “predictions.png”

}));

res.end();

});

 

// listenを開始する

app.listen(3000);

 

  • 次にブラウザ側のインターフェイスとなるhtmlを用意する。Inde.htmlに以下のコードを貼り付ける。詳しくはコード中のコメントを参照

<!DOCTYPE html>

<html lang=”ja”>

<head>

<meta charset=”UTF-8″>

<title>Darknet Web</title>

<style>

.result-img {

max-width: 50vw;

}

</style>

</head>

<body>

<form method=”post” action=”./” enctype=”multipart/form-data”>

<input id=”input-file” type=”file” name=”input-img” accept=”image/*”>

<input id=”submit-button” type=”submit” value=”送信”>

</form>

<progress id=”progress-bar” style=”display: none”></progress>

<img class=”result-img”>

 

<script>

const submitBtn = document.querySelector(‘#submit-button’);

const progBar = document.querySelector(‘#progress-bar’);

const resultImg = document.querySelector(‘.result-img’);

 

// submitボタンがクリックされたら

submitBtn.onclick = (evt) => {

// ブラウザデフォルトの挙動をキャンセルする

evt.preventDefault();

 

// プログレスバーを表示する

progBar.style.display = ‘inline’;

 

// 情報をfetchするためのヘッダとボディを作成する

const headers = { ‘Accept’: ‘application/json’ };

const body = new FormData();

body.append(‘input-img’, document.querySelector(‘#input-file’).files[0]);

 

// Fetch APIを利用してサーバに画像を送り返答を待つ

// Fetch APIの詳しい利用方法は以下のURLを参照

// https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API/Using_Fetch

fetch(‘./’, {method: ‘POST’, headers, body})

.then(response => response.json())

.then((result) => {

// 帰ってきたJSONに画像のパスが含まれているので

// それをimg要素にセットする

const path = result.path;

resultImg.src = path;

 

// プログレスバーを非表示にする

progBar.style.display = ‘none’;

});

};

</script>

</body>

</html>

起動と動作確認

  • ここまでできたら、以下のコマンドでサーバを立ち上げる:

nodejs app.js

  • サーバが立ち上がったらブラウザで http://localhost:3000/ にアクセスする
  • あとはブラウザ上から画像を送信して、処理が終わるまでしばらく待てば認識ラベルがついた画像が表示される。
Copyright(c) 2011 株式会社アプリズム|apprhythm All Rights Reserved.