LoginSignup
6
5

More than 1 year has passed since last update.

LineBotに顔画像を送信し、Face APIを使って表情判定してもらう

Last updated at Posted at 2021-11-14

はじめに

Qiita内にはNode.jsやFace APIを使って画像を認識させるLine Botの記事が少ない印象でした。

今回は下記記事を参考にしました。

GitHubからソースコードを引っ張ってきて、実装しました。

下準備

下記記事を参考にLine Botを使用できる状態にします。

npm init -y
npm i @azure/cognitiveservices-face @azure/ms-rest-azure-js
でAzureを使えるようにします。

全体像

'use strict';

const fs = require("fs");
// Azure Face APIを使うための準備
const { FaceClient } = require("@azure/cognitiveservices-face");
const { CognitiveServicesCredentials } = require("@azure/ms-rest-azure-js");
const faceKey = ""; //個人のKey
const faceEndPoint = ""; //個人のEndPoint
const cognitiveServiceCredentials = new CognitiveServicesCredentials(faceKey);
const faceClient = new FaceClient(cognitiveServiceCredentials, faceEndPoint);

//APIを叩ける
const express = require('express');
const line = require('@line/bot-sdk');
const PORT = process.env.PORT || 3000;

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

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);

async function handleEvent(event) {
  let message = {
    type: 'text',
    text: null
  };
  if(event.message.type === "image"){
    console.log("画像を検出しました");
    try{
      //画像を取得
      const image = await downloadContent(event.message.id);
      // 画像を取得し終わったらFace APIに送信して、顔検出を行う
      const faceList = await faceClient.face.detectWithStream(image, {
        returnFaceAttributes: ["age", "smile", "makeup", "glasses", "facialHair"], // ここにカンマ(,)区切りでパラメータを追加する
      });
      message = {
        type: 'text',
        text: ' 年齢 :'+faceList[0].faceAttributes.age+''
          +'\n 笑顔 :'+ faceList[0].faceAttributes.smile * 100 + ''
          +'\n ひげ :'+ faceList[0].faceAttributes.facialHair.beard
          +'\nメイク:'+ faceList[0].faceAttributes.makeup.eyeMakeup
          +'\nメガネ:'+ faceList[0].faceAttributes.glasses

      };
      return client.replyMessage(event.replyToken, message);
    }catch (e) {
      console.error(e);

      return client.replyMessage(event.replyToken, {
        type: "text",
        text: "画像取得or画像分析中にエラーが発生しました。",
      });
    }
  }else{
    message = {
      type: 'text',
      text: '申し訳ありません。個別メッセージには対応しておりません。',
    };
    return client.replyMessage(event.replyToken, message);
  }
}

async function downloadContent(messageId, downloadPath = "./image.png") {
  const data = [];
  return client.getMessageContent(messageId).then(
    (stream) =>
      new Promise((resolve, reject) => {
        const writable = fs.createWriteStream(downloadPath);
        stream.on("data", (chunk) => data.push(Buffer.from(chunk)));
        stream.pipe(writable);
        stream.on("end", () => resolve(Buffer.concat(data)));
        stream.on("error", reject);
      })
  );
}
app.listen(PORT);
console.log(`Server running at ${PORT}`);

Line Botに対して、imageタイプのメッセージが送信されたら、動く仕様です。
それ以外のタイプには、申し訳ありません。個別メッセージには対応しておりません。と出力されます。

今回は「笑顔」をメインとしていますが、他にもいろいろあるみたいです。

追記

■GitHubからソースコードをコピーしたときの注意点
1時間でLINE Botを作るハンズオンのサイトを参考にBot作成をした場合、
ソースコード115行目:
app.post("/", line.middleware(config), (req, res) => {
 ↓
app.post("/webhook", line.middleware(config), (req, res) => {
へと変更が必要です。(2021/11/23)

6
5
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
6
5