Edited at

LINE動物図鑑の作り方


概要

スマホで撮影した動物の写真をLINE Bot宛てに送ると、

動物の種類を教えてくれる動物図鑑。

image.png


更新履歴

2019/09/07 デグーとチンチラとモルモットを追加。(結構げっ歯類の判定が厳しくなってきた!)

2019/09/01 ペンギンの種類を追加。

2019/08/30 一部要望のあった動物を追加。(ペンギン、トリ ※主にカラス を追加)

その他の動物もリクエストお待ちしております。

2019/08/20 LINEBotのQRコード追加


作ったきっかけ

2019年8月某日からWindows10のログイン画面に急遽出現したカワウソ。

このカワウソの種類を簡単に調べるにはどうすれば良いか?

道端で動いている怪しい動物はなんていう動物なのか?

という非日常的な問題を簡単に解決できるようにしたい。


完成デモ

https://www.youtube.com/watch?v=PeuqqgVQMRU&feature=youtu.be

※クリックするとYoutubeを開きます。

デモ


実施環境

OS:Windows10 Pro 64ビット

画像認識:Azure CustomVisonService

動作:Node.js

デプロイ環境:Now


事前準備(必要ツール)


  1. Python3.7.4(32ビット)のインストール
    ダウンロード先:
    https://www.python.org/ftp/python/3.7.4/python-3.7.4.exe


Add Python 3.7 to PATHのチェックは忘れずに!

image.png

2.Python起動確認

コマンドプロンプトから Python --versionを入力

Python3.7.4などインストールしたバージョンが表示されればOK。

image.png

3.pipの確認(Pythonと同時にインストールされるらしい)

コマンドプロンプトから pip -V を入力

image.png

4.google-images-downloadをインストールします。

Pythonで作成されているため、導入はコマンドライン上から'pip'のコマンドを使ってインストールします。

コマンドプロンプトを立ち上げ、下記のコマンドを入力。

pip install google_images_download

image.png

Successfully ~が表示されれば成功。


学習用の画像データの準備

google-images-download を使うことで、指定したキーワードの画像を一括入手できます。

1.コマンドプロンプトに下記のコマンドを入力し、実行します。

googleimagesdownload -k 'コツメカワウソ' -la Japanese -l 100 -s medium

バッチファイル化することでまとめて実行できます。

img-download.bat

cd C:\Users\[アカウント名]\Desktop\download

googleimagesdownload -k 'コツメカワウソ' -la Japanese -l 100 -s medium -co white

googleimagesdownload -k 'コツメカワウソ' -la Japanese -l 100 -s medium -co black

googleimagesdownload -k 'コツメカワウソ' -la Japanese -l 100 -s medium -co red

googleimagesdownload -k 'コツメカワウソ' -la Japanese -l 100 -s medium -co green

googleimagesdownload -k 'コツメカワウソ' -la Japanese -l 100 -s medium -co gray

googleimagesdownload -k 'コツメカワウソ' -la Japanese -l 100 -s medium -co yellow



image.png

ダウンロードできる画像数は100を上限に指定できます。

100毎より多くダウンロードしたい場合は、chromedriver.exeが別途必要になります。

※オプションに -co red を付けると赤いカワウソがダウンロードできます。

各色毎にダウンロードして素材データとして使いました。


学習用データの登録


  1. Azure Cognitive Vision Servicesにアクセスします。

    https://www.customvision.ai/projects


  2. NEW PROJECTをクリックしてプロジェクトを作成します。

    image.png


  3. 各種項目を埋めていきます

    Name:プロジェクト名

    Description:プロジェクトの説明

    Resource:AzurePortalで作成したリソースを選択します。無い場合は、Create Newから作成します。

    ProjectTypes:Classificationを選択します。

    Classification Types:Multilabel(Multiple tags per image)を選択します。

    Domains:Generalを選択します。


Create projectをクリックします。

image.png

4.Training Images → Add imagesをクリックしてダウンロードしたファイルをまとめてアップロードします。

image.png

アップロード時に関連するタグを入力してUpload n filesをクリックします。

image.png

各動物ごとタグを付けてアップロードしていきます。

5.アップロードとタグ付け完了後、Train をクリックします。

image.png

Fast Training を選択し、Trainをクリックします。

※Advanced Trainingを選択するとかなり時間がかかります。

image.png

6.トレーニング完了後、QuickTestボタンより、分類したい画像をアップロードしてテストします。

99%コツメカワウソと判断されたのでOKですね。

image.png


LINE Bot との連携

1.Azure Custom Vision ServicesのPerformanceからPublishをクリックし、Prediction APIを発行する。

※下記のようなresourceなんちゃらのエラーで発行できない場合は、

ProtoOut Studio 講師長田中さん が書いたここの記事を参考にしてください。

https://protoout.studio/posts/custom-vision-project-publish-error

image.png

2.Prediction APIが表示された場合は、APIキーを控えておきます。

image.png

3.LINE BoTを作成します。

LINE Botの簡単な作り方はこちらの@n0bisukeさんの記事を参考にしてください。

https://qiita.com/n0bisuke/items/ceaa09ef8898bee8369d

4.下記のソースを参考にしてNowでデプロイすれば完成です。


Node.jsのソース


server.js

'use strict';

const express = require('express');
const line = require('@line/bot-sdk');
const PORT = process.env.PORT || 3000;
const fs = require('fs');
const bodyParser = require('body-parser');
const Request = require('request');
const cv = require('customvision-api');

const config = {
channelSecret: '作成したBOTのチャンネルシークレット',
channelAccessToken: '作成したBOTのチャンネルアクセストークン'
};

const app = express();
app.use(bodyParser.json());
let middle = line.middleware(config);
const client = new line.Client(config);

app.post('/webhook', (req, res) => {
console.log(req.body.events);

if(req.body.events[0].message.type !== 'image') return;

// ユーザーがLINE Bot宛てに送った写真のURLを取得する
const options = {
url: `https://api.line.me/v2/bot/message/${req.body.events[0].message.id}/content`,
method: 'get',
headers: {
'Authorization': 'Bearer [アクセストークン]' ,
},
encoding: null
};

Request(options, function(error, response, body) {

if (!error && response.statusCode == 200) {
//保存

console.log(options.url + '/image.jpg');
let strURL = options.url + '/image.jpg';

//Nowでデプロイする場合は、/tmp/のパスが重要
fs.writeFileSync(`/tmp/` + req.body.events[0].message.id + `.png`, new Buffer(body), 'binary');

const filePath = `/tmp/` + req.body.events[0].message.id + `.png`;

//Azure Custom Vision APIの設定
const config = {
"predictionEndpoint": '[Iteration]',
"predictionKey": '[predictionKey]'
};

cv.sendImage(
filePath,
config,
(data) => {
console.log(data);
let strName = data.predictions[0].tagName;
let strTarget = "";

let strName2 = "";
let strTarget2 = "";

if (data.predictions[0].probability > 0.8) {
strTarget="だねー"

}else if(data.predictions[0].probability > 0.4){
strTarget="っぽいねー"

}else if(data.predictions[0].probability > 0.2){
strTarget="みたいだねー"

}else if(data.predictions[0].probability > 0.1){
strTarget="かな?ちょっとよくわからないねー"

}else{
console.log(data.predictions[0].tagName);
strName="なんのどうぶつか"
strTarget="わからないねー"

}

if (data.predictions[1].probability > 0.2) {
strName2='\n' + data.predictions[1].tagName
strTarget2="っぽいところもあるよねー"
}

client.replyMessage(req.body.events[0].replyToken, {
type: 'text',
text: 'これは' + strName + strTarget + strName2 + strTarget2 //実際に返信の言葉を入れる箇所
});

try {
fs.unlinkSync(filePath);
return true;
} catch(err) {
return false;
}

return;

},
(error) => { console.log(error) }
);

} else {
console.log('imageget-err');
}
});
});

(process.env.NOW_REGION) ? module.exports = app : app.listen(PORT);
console.log(`Server running at ${PORT}`);



最後に

今回作成したLINEBotのQRコードはAzureCustomVisonを使用しているため、

金額がとんでもないことになるのが嫌なので公開しません。

興味ある方はツイッターでDMください。


2019/08/29 なんか大丈夫そうなのでQRコード追加。

image.png