空の画像で天気を予想してくれるLINE BOTを作った

機械学習とLINE BOT作りに興味があったので、この二つを組み合わせて、撮影した空や雲の画像から天気を予想してくれるLINE BOTを作りました。
# 参考にした記事
[画像認識AIを使ったLINE BOTの作り方](https://qiita.com/2zn01/items/7f7b8c57054f67ef9528 )
さらに、上記の記事の作者様が作成された、[AIメーカー](https://aimaker.io/)で天気予想の部分はまるっと作成可能でした。

# AIメーカーでAIを作る
![スクリーンショット 2020-12-07 21.10.16.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/442492/ab5ebd0b-c815-480f-6aad-428252fabc0c.png)

「AIに識別させるラベル」という項目がAIが返す結果になります。
今回は「すぐに雨が降るか」「数時間後に雨が降るか」「雨は降らないか」の3つの結果を返すようにしました。
AIの名前など適宜入力をしたら、いよいよ学習に入ります。
![スクリーンショット 2020-12-07 21.07.11.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/442492/46dfa48b-bc8a-c7b5-ea2b-86df593a10e5.png)
学習方法は、作成したラベルに該当する画像をひたすら読み込ませるだけです。
[この辺のサイト](https://yamahack.com/71)から雨を降らせる雲の名前を調べて、「検索して画像を追加」ボタンを押すだけで自動的に画像を収集して登録してくれます。便利！
もちろん全然関係のない画像を拾ってきてしまうこともあるので、その場合は手動で削除します。
それぞれのラベルに画像を登録してAIの作成は完了です。
# LINE BOT を作る
アカウントの作成方法は[公式ページの1~5](https://developers.line.biz/ja/docs/messaging-api/getting-started/#using-console)を参照しました。
![スクリーンショット 2020-12-18 21.34.39.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/442492/dedc2817-a1ab-3a80-fb68-1ac0dd33df8f.png)
画像のように「応答メッセージ」と「あいさつメッセージ」は無効に設定しておき、「Webhookの利用」を有効にしておきます。
同じ設定画面から「チャンネルアクセストークン」を発行しておきます。

あとはGoogle Apps Script に下記コードを記述します。

```
var AIMAKER_MODEL_ID = AIメーカーで作成したモデルのID;
var AIMAKER_API_KEY = AIメーカーのAPIキー;
var LINE_ACCESS_TOKEN = LINE BOTのチャンネルアクセストークン;

function doPost(e){
  try {
    var json = JSON.parse(e.postData.contents);
    var token= json.events[0].replyToken;
    var url = 'https://api.line.me/v2/bot/message/'+ json.events[0].message.id +'/content/';
    var image = getImage(url);
    var base64 = Utilities.base64Encode(image.getContent());
    var message = getResult(base64);
    if (message == '') {
      message = "識別できませんでした。";
    }
    sendLineMessage(message, token);
  } catch (e) {
    message = "処理に失敗しました。"
    sendLineMessage(message, token);
  }
}

function getImage(url){
  return UrlFetchApp.fetch(url, {
    'headers': {
      'Content-Type': 'application/json; charset=UTF-8',
      'Authorization': 'Bearer ' + LINE_ACCESS_TOKEN,
    },
    'method': 'GET'
  });
}

function getResult(base64){
  var result = '';
  var url = 'https://aimaker.io/image/classification/api';
  var payload = {
    "id": AIMAKER_MODEL_ID,
    "apikey": AIMAKER_API_KEY,
    "base64": base64
  };
  var response = UrlFetchApp.fetch(url, {   
    method: 'POST', 
    payload: payload, 
    muteHttpExceptions: true
  });
  response = response.getContentText();
  var json = JSON.parse(response);
  var labels = sortLabel(json.labels);
  if (labels[0].label && labels[0].score){  
    result = 'この画像の診断結果は、「' + labels[0].label + '： ' + (Math.round(labels[0].score * 10000) / 100) + "％」です！\n\n";
  }
  for (var i in labels) {
    if (labels[i].label && labels[i].score) {
      result = result + labels[i].label + '： ' + (Math.round(labels[i].score * 10000) / 100) + "％\n";
    }
  }
  return result;
}

function sortLabel(labels){
  labels.sort(function(a,b){
    if (a.score > b.score) return -1;
    if (a.score < b.score) return 1;
    return 0;
  });
  return labels;
}

function sendLineMessage(message,token){
  var url = "https://api.line.me/v2/bot/message/reply";
  return UrlFetchApp.fetch(url, {
    'headers': { 
      'Content-Type': 'application/json; charset=UTF-8',
      'Authorization': 'Bearer ' + LINE_ACCESS_TOKEN,
    },
    'method': 'POST',
    'payload': JSON.stringify({ 
      'replyToken': token,
      'messages': [
        { 
          "type": "text",
          "text": message
        } 
      ], 
    })
  });
}
```
コードの記述が済んだら、公開タブのウェブアプリケーションとして導入を選択し、以下のように実行します。
Execute the app as（次のユーザーとしてアプリケーションを実行）：自分
Who has access to the app（アプリケーションにアクセスできるユーザー）：全員（匿名ユーザーを含む）
初回のみGoogleアカウントへのアクセス許可が出るのでこれを許可します。
発行されたURLは、LINE BOTの管理画面のWebhook URLに設定します。
ちなみに、コードを修正等で更新した場合は、Project versionを New としないとなぜかうまく更新されません。これで地味に詰まりました…。
#完成したもの
![967qpnwu.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/442492/84cdaced-ad87-0bd0-7948-53d600aecd3d.png)
肝心の精度ですが、快晴の日の空で試してみたものの
![IMG_3797.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/442492/0af540fd-58c8-be95-bfa4-2470702e173d.jpeg)
うーん…？？？とりあえず今すぐには雨は降らないということですね！
まぁ普通に天気予報見ろってことですが、機械学習の片鱗を味わえたことと、LINE BOTは意外と簡単に作れると知れたのがよかったです。
特にLINE BOTとGASの組み合わせはいろいろ使えそうな気がします。
もう少し実用的なものも今度作ってみたいなと思いました。

###おまけ
BOTからの返信に画像を使うこともできます。
[公式](https://developers.line.biz/ja/reference/messaging-api/#image-message)にある通り、返信の部分をこのようにすると画像を返すこともできます。

```
'messages': [
        { 
          "type": "image",
          "originalContentUrl": message,
          "previewImageUrl": message
        } 
      ], 
```
originalContentUrlとpreviewImageUrlには画像のパスを指定します。
Googleドライブに置いてある画像を使いたかったので調べたところ、共有設定を「リンクを知っている全員」にして、画像パスを``https://drive.google.com/uc?id=画像ID``と指定するとできました。
画像IDは共有リンクの``https://drive.google.com/file/d/この部分です/view?usp=sharing``
###おまけでできたもの
古のネタ、〇〇のAAくださいのノリで、送った画像の紅度に応じた紅だAAを返してくれます。
とてもくだらないですごめんなさい。
![452lbjsl.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/442492/15d34fea-d076-11dd-c50c-cb2e37e143f4.png)