LINEで画像にある日本語を認識しよう


モチベーション

日本で働いている私にとっては辞書は一番使っているプログラムです。
もちろん、わからない単語がたくさんあります。普通、わからない単語があったら、単語をコピーして辞書にペーストしますが、時々写真にある単語に対して大変になりました。その漢字一つ一つを手で描けなければなりません。
で、今回、写真のテキストをAIで認識してもらって、デジタルの文字コードに変換するLINE BOTを作りましょう。

 概要

要素

今回のシステムは要素が3つあります

  • クライアント:これユーザにつながる場所です。テキストの写真をアップロードして結果が表示されるところです。今回使いたいサービスはLine Botです。
  • サーバー:クライアントから画像をもらって、OCRサービスに送って、結果を処理してクライアントに送るところです。
  • OCRサービス:OCR(Optical Character Recognition:光学文字認識)とは、活字の文書の画像(通常イメージスキャナーで取り込まれる)を文字コードの列に変換するソフトウェアである(ソース:ウィキペディア)。

フロー

① サーバーはLineAPIでユーザーが送ったもらった画像を読んで、ファイルを保存するステップです。
② ステップ1のファイルをグーグルのOCRサービスに送ります。
③ グーグルのレスポンスから必要部分を抽出します。
④ ステップ3の結果をLineAPIでユーザーに返信します。

コード


'use strict';

const fs = require('fs');
const keyConfig = require('./config');
const express = require('express');
const bodyParser = require('body-parser');
const request = require('request');
const app = express();
app.use(bodyParser.json());
const line = require('@line/bot-sdk');
const vision = require('@google-cloud/vision');

const PORT = process.env.PORT || 3000;
const config = {
    channelSecret: keyConfig.line.channelSecret,
    channelAccessToken: keyConfig.line.channelAccessToken
};

const lineClient = new line.Client(config);

async function googleOCR(fileName, token) {
    const googleClient = new vision.ImageAnnotatorClient();

    googleClient.documentTextDetection(fileName)
    .then(response => {
        return lineClient.replyMessage(token, {
            type: 'text',
            text: response[0].fullTextAnnotation.text
        });
    })
    .catch(err => {
        console.error(err);
    });
};

const sampleFunction = async (event) => {
    const options = {
        url: `https://api.line.me/v2/bot/message/${event.message.id}/content`,
        method: 'get',
        headers: {
            'Authorization': 'Bearer ' + keyConfig.line.channelAccessToken,
        },
        encoding: null
    };
    const fileName = './image.jpg';

    request(options, function(error, response, body) {
        if (!error && response.statusCode == 200) { 
            fs.writeFileSync(fileName, new Buffer.from(body), 'binary');
            console.log('file saved');
        }
    });

    return googleOCR(fileName, event.replyToken);
};

async function handleEvent(event) {
    if(event.message.type !== 'image') {
        return;
    }
    return sampleFunction(event);
}


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

app.listen(PORT);
console.log(`ポート${PORT}番でExpressサーバーを実行中です…`);

結果

参考:
LINE BOTからNode.jsで画像を受け取って保存する
Google Nodejs API