9
4

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

RaspberryPiで撮った写真をCustom Vision Serviceで画像判定してどの猫がいるかLINEに返す

Last updated at Posted at 2020-05-13

はじめに

LINEBotからRaspberryPiで写真を撮ってLINEにおくる!で作ったLINEBotにAI機能を追加してどの猫がいるか教えてくれるものを作りました。

概要

LINEBotからRaspberryPiを動かして写真を撮り、Gyazoに送って画像判定で何が映っているかと撮影した写真をLINEに送るものです。
ppt.png

画像判定

画像判定はMicrosoft Custom Vision Serviceを使用。
茶色と白黒とグレーの3匹のねこを学習させ、mixとして色々な猫を追加学習させて、3匹のどの猫に近いかを教えてくれます。
スクリーンショット 2020-05-13 22.28.03.png
3匹以外の猫を判定するとmixが一番高い値で出ます!(catタグは全ての猫に追加)
スクリーンショット 2020-05-13 22.26.38.png

できたもの

使い方

RaspberryPiを猫がよくいる場所に置きます。
猫が見たいので LINEBotに「ねこ」と入れます。
(「ねこ」以外のワードには「何が見たいの?」と返してきます。)
写真を撮るのに時間がかかるので、「写真撮ってくるから待っててねー」、とつなぎのワードが入ります。
写真を撮って送るときに Azure Cognitive Vision ServicesのCustom Vision Serviceを使用してどの猫がいるかを画像を分類して、10秒ほどすると猫の種類と写真が送られてきます。

環境

MacBook Pro macOS Mojave
 Visual Studio Code 1.44.0
Azure Cognitive Vision Services
 Custom Vision Service
RaspberryPi 3B
 Release: 10
 Codename: buster
 Node.js v12.16.3
 npm v6.14.4
 ngrok
Pi camera
洗濯バサミ

コード

node.js
'use strict';
const express = require('express');
const line = require('@line/bot-sdk');
const axios = require('axios');
const PORT = process.env.PORT || 3000;
const Gyazo = require('gyazo-api');
const gyazoclient = new Gyazo('***');
const config = {
  channelSecret: '***',
  channelAccessToken: '***'
};
const app = express();
let whichCat;

app.get('/', (req, res) => res.send('Hello LINE BOT!(GET)')); //ブラウザ確認用(無くても問題ない)
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);
async function handleEvent(event) {
  if (event.type !== 'message' || event.message.type !== 'text') {
    return Promise.resolve(null);
  }
  let mes = event.message.text;
  if (event.message.text.match("ねこ")) {

    await client.replyMessage(event.replyToken, {
      type: "text",
      text: '写真を撮ってくるからちょっと待っててね'
    });
    await nyanpi();
    return nyancoPic(event.source.userId);
  }
  else {
    return client.replyMessage(event.replyToken, {
      type: "text", text: '何が見たいのかな?'
    });
  }
}
const nyanpi = async (userId) => {
  const PiCamera = require('pi-camera');
  const myCamera = new PiCamera({
    mode: 'photo',
    output: `${__dirname}/nyan.jpg`,
    width: 640,
    height: 480,
    nopreview: true,
  });
  await myCamera.snap()
  await gyazoclient.upload('./nyan.jpg', {
    title: "my picture",
    desc: "upload from nodejs"
  })
}
//Custom Vision Service
const sendCustomVision = async (imageURL) => {
  const CUSTOM_VISION_API_ENDPOINT_URL = '***';
  // Prediction-Keyの値を Prediction-Key ヘッダーに入れる
  // JSONで送るので Content-type ヘッダーに application/json 指定
  const configCustomVisionAPI = {
    url: CUSTOM_VISION_API_ENDPOINT_URL,
    method: 'post',
    headers: {
      'Content-type': 'application/json',
      'Prediction-Key': '***'
    },
    data: {
      url: imageURL
    }
  };
  // axiosの送信設定
  let responseCustomVision;
  try {
    // POSTリクエストで送る
    responseCustomVision = await axios.request(configCustomVisionAPI);
    console.log("post OK");
    // データ送信が成功するとレスポンスが来る
    console.log(responseCustomVision.data);
    // 全てのタグにcatが含まれているので、近似値が高いものがcatタグの時は2番目を返す
    const catTag = responseCustomVision.data;
    if (catTag.predictions[0].tagName === "cat") {
      whichCat = catTag.predictions[1].tagName
    } else {
      whichCat = catTag.predictions[0].tagName;
    }
  } catch (error) {
    console.log("post Error");
    // ダメなときはエラー
    console.error(error);
  }
}
//gyazoから最新の写真URLを取得
const nyancoPic = async (userId) => {
  const response = await gyazoclient.list()
  const gyazoimgUrl = response.data[0].url;
//画像判定に送る
  const sendcstmvison = await sendCustomVision(gyazoimgUrl);
//タグの名前を猫の見た目に置き換え
  if (whichCat === "chairo") {
    whichCat = "ちゃいろ";
  } else if (whichCat === "shirokuro") {
    whichCat = "しろくろ";
  } else {
    whichCat = "グレー";
  }
  return client.pushMessage(userId, [{
    type: 'image',
    originalContentUrl: gyazoimgUrl,
    previewImageUrl: gyazoimgUrl
  },
  {
    type: "text", text: `${whichCat}の猫がいるよ`
  }]);
}
app.listen(PORT);
console.log(`Server running at ${PORT}`);

参考サイト

Computer Vision サービスを使用した画像処理 - Learn | Microsoft Docs

感想

AIが簡単に実装できた
グレーがシンガプーラという猫種で他のことめちゃくちゃ顔が同じなのでシンガプーラ判定やってみたい。
ngrokなので早く何かにdeployしたい。

9
4
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
9
4

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?