LoginSignup
105
67

More than 3 years have passed since last update.

LINE動物図鑑の作り方

Last updated at Posted at 2019-08-27

概要

スマホで撮影した動物の写真を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

105
67
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
105
67