プログラミング素人が画像認識AIで犬種回答サービスを作ってみた

プログラミング初心者でもAIサービスを触ってみることができたので記録します。

##自分の技術レベル
・ProgateでHTML/CSS、JavaScript、Node.JSを受けた
・Expressフレームワークでget通信とpost通信を扱えるようになってきた
・JSのasync/awaitの概念が少しだけ理解できてきた
・Promiseは理解できていない


##今回インプットしたもの
Microsoftが提供するCustomVison」というサービスの存在を知りました。

https://azure.microsoft.com/ja-jp/services/cognitive-services/custom-vision-service/

タグ付けした画像をため込んで学習させる
↓
学習した内容に基づいて、新たに画像を見せるとどのタグに近い画像なのか判断する、というサービスです。
すごい！！

更にAPI化されているので、外部と連携させることができるようです。

##今回挑戦したアウトプット
CustomVisonに犬の画像を学習させてLINEbotとつなげることで、**「画像を投げたら犬種を分析して応答してくれるLINEbot」**を作ってみました。

まず犬の画像をため込んでタグ付けして、機械学習させます。
![2020-05-12_21h28_19.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/599091/35dbc73e-5d4e-6446-4d55-e4323153ea2b.png)

そして以前作ったLINEbotのプログラムとつなげる。

```JS
'use strict';

const express = require('express');
const line = require('@line/bot-sdk');
const axios = require('axios');
const PORT = process.env.PORT || 3000;

const config = {
  channelSecret: '', //チャンネルシークレット
  channelAccessToken: '' //チャンネルアクセストークン
};

const app = express();

app.post('/webhook', line.middleware(config), (req, res) => {
    console.log(req.body.events);
    Promise
      .all(req.body.events.map(handleEvent))
      .then((result) => res.json(result));
});

const client = new line.Client(config);

function handleEvent(event) {
  console.log(event);
  
  // 今回は画像投稿を通す
  if (event.type !== 'message' || event.message.type !== 'image' ) {
    return Promise.resolve(null);
  }

  let mes = ''
  if(event.message.type === 'image'){
    mes = '画像を判定しています！';
    getFaceDetect2(event.message.id, event.source.userId, config.channelAccessToken );
  } else{
    mes = event.message.text;
  }

  

  return client.replyMessage(event.replyToken, {
    type: 'text',
    text: mes
  });
}

const getFaceDetect2 = async (messageId , userId, accessToken) => {
  console.log("getFaceDetect2");
  console.log(messageId);
  console.log(accessToken);

  //LINEbotから画像取得
  const configImageAPI = {
    url: `https://api.line.me/v2/bot/message/${messageId}/content`,
    method: 'get',
    headers: {
        'Authorization': 'Bearer ' + accessToken,
    },
    responseType: 'arraybuffer'
  };

  let responseImageAPI;
  try {
    // axios はRequest Configで受信データのタイプを設定できる。今回は arraybuffer が適切。
    responseImageAPI = await axios.request(configImageAPI);
    console.log('image data get');
  } catch (error) {
    console.log('post Error');
    console.error(error);
  }

  //Custom Vision APIへのリクエスト

  const CUSTOM_VISION_API_ENDPOINT_URL = 'CustomVisionAPIのURL';

  // JSONで送るので Content-type ヘッダーに application/json 指定
  const configCustomVisionAPI = {
    url: CUSTOM_VISION_API_ENDPOINT_URL,
    method: 'post',
    headers: {
      'Content-type': 'application/octet-stream',
      'Prediction-Key':''　//CustomVisionAPIのプレディクションキー
    },
    data: responseImageAPI.data
  };

  // axiosの送信設定
  let responseCustomVision;
  try {
    // POSTリクエストで送る
    responseCustomVision = await axios.request(configCustomVisionAPI);
    console.log("post OK");
    // データ送信が成功するとレスポンスが来る
    console.log(responseCustomVision.data.predictions[0].tagName);
  } catch (error) {
    console.log("post Error");
    // ダメなときはエラー
    console.error(error);
  }
  
  //LINEbotから返信
  await client.pushMessage(userId, {
    type: 'text',
    text: JSON.stringify(responseCustomVision.data.predictions[0].tagName),
  });
}

app.listen(PORT);
console.log(`Server running at ${PORT}`);

```


ちゃんと画像解析して回答してくれました！

![2020-05-12_21h40_35.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/599091/c15fa350-4a00-6d03-fe7f-55638f8c29ab.png)

日本語で渡そうとするとエラーになってしまい解決できなかったので英語のままです。

##振り返り
・やっぱり日本語で回答させたい
・今は柴犬・パグ・チワワの3種類しか学習させていないので実用化させるならもっと学習させる必要がある。
・学習にも画像を1つ1つ手でアップしてタグ付けするマンパワーがかかる。
・勝手に学習してくれたらもっと楽になるけどそんな技術あるのか気になる。