はじめに
LINEとGoogle Cloud Vision API を使用して 画像解析を行うBOTを作成しました。
Google Cloud Vision API
- Google Cloud Platform(GCP)が提供する画像認識サービスです。
- GCPで新しくプロジェクトして、
Cloud Vision API
を有効にしてトークンを発行します。
事前準備
- GoogleDriveにてGoogleAppsScriptを開いて、以下のスクリプトを実装します。
-
LINE_CHANNEL_TOKEN
にLINE Messaging APIで発行したトークンを指定します。 -
GOOGLE_API_KEY
にGoogle Cloud Vision APIで発行したトークンを指定します。 -
SSID
にスプレッドシートのIDとSSN_USER
にシート名を指定します。
main.gs
/**
* 画像解析BOT
*/
const LINE_CHANNEL_TOKEN = '*****'; // LINE NOTIFYのアクセストークン
const GOOGLE_API_KEY = '*****';
const SSID = '*****';
const SSN_USER = 'user';
フォロー登録
フォロー解除
リプライ
ユーザーが画像を入力するとLINE Messaging API
からGASにPOSTが通知されます。GASでは、画像を取得して、GoogleCloudVisionに解析依頼を行います。その後、解析結果をLINE Messaging API
にPOSTで返します。
main.gs
/**
* メッセージイベント処理
* @param {Object} reqEvent
*/
function executeMessage(reqEvent) {
let msgList = [];
let user = getUser(reqEvent.source.userId);
if (user) {
switch (reqEvent.message.type) {
case 'image':
let content = getLineContent(reqEvent.message.id);
let result = getAnnotate(content.getBlob());
console.log(result);
for (let i in result.responses) {
let retObj = result.responses[i];
for (let key of Object.keys(retObj)) {
let msg = null;
let value = retObj[key];
switch (key) {
case 'webDetection':
msg = getMsgWebDetection(value);
break;
case 'labelAnnotations':
msg = getMsgLabelAnnt(value);
break;
case 'textAnnotations':
msg = getMsgTextAnnt(value);
break;
case 'landmarkAnnotations':
msg = getMsglandmarkAnnt(value);
break;
case 'logoAnnotations':
msg = getMsglogoAnnt(value);
break;
}
if (msg) {
msgList.push({
'type': 'text',
'text': msg,
});
}
}
}
if (0 < msgList.length) {
console.log(JSON.stringify(msgList).replace('\n', ''));
sendLineReply(reqEvent.replyToken, msgList);
}
break;
}
}
}
/**
* WEB検出のメッセージを取得する
* @param {Object} value
*/
function getMsgWebDetection(value) {
let msg = `【WEBの検出】\n\n`;
for (let i in value.webEntities) {
let item = value.webEntities[i];
msg += `- ${LanguageApp.translate(item.description, 'en', 'ja')}\n`;
}
for (let key of Object.keys(value)) {
switch (key) {
case 'fullMatchingImages':
msg += `\n<< 完全一致 >>\n`;
for (let j in value[key]) {
let item = value[key][j];
msg += `[${parseInt(j) + 1}] ${item.url}\n`;
}
break;
case 'partialMatchingImages':
msg += `\n<< 部分一致 >>\n`;
for (let j in value[key]) {
let item = value[key][j];
msg += `[${parseInt(j) + 1}] ${item.url}\n`;
}
break;
case 'visuallySimilarImages':
msg += `\n<< 類似 >>\n`;
for (let j in value[key]) {
let item = value[key][j];
msg += `[${parseInt(j) + 1}] ${item.url}\n`;
}
break;
}
}
return msg;
}
/**
* ラベル検出のメッセージを取得する
* @param {Array} value
*/
function getMsgLabelAnnt(value) {
let msg = '【ラベルの検出】\n\n';
for (let i in value) {
let item = value[i];
msg += `- ${LanguageApp.translate(item.description, 'en', 'ja')}\n`;
}
return msg;
}
/**
* 文字検出のメッセージを取得する
* @param {Array} value
*/
function getMsgTextAnnt(value) {
return `【文字の検出】\n\n${value[0].description}\n`;
}
/**
* 場所検出のメッセージを取得する
* @param {Array} value
*/
function getMsglandmarkAnnt(value) {
let msg = '【場所の検出】\n\n';
for (let i in value) {
let item = value[i];
msg += `- ${LanguageApp.translate(item.description, 'en', 'ja')}\n`;
for (let j in item.locations) {
let loc = item.locations[j];
msg += `https://www.google.com/maps?q=${loc.latLng.latitude},${loc.latLng.longitude}\n`;
}
msg += `\n`;
}
return msg;
}
/**
* ロゴ検出のメッセージを取得する
* @param {Array} value
*/
function getMsglogoAnnt(value) {
let msg = '【ロゴの検出】\n\n';
for (let i in value) {
let item = value[i];
msg += `- ${item.description}\n`;
}
return msg;
}
/**
* Googleに画像を送信する
* @param {Object} file ファイル
*/
function getAnnotate(file) {
let url = `https://vision.googleapis.com/v1/images:annotate?key=${GOOGLE_API_KEY}`;
let options = {
'method': 'get',
'headers': {
'Content-Type': 'application/json; charset=UTF-8',
},
'payload': JSON.stringify({
requests: [{
image: {
content: Utilities.base64Encode(file.getBytes())
},
features: [{
type: 'WEB_DETECTION', // WEBの検出
maxResults: 5
},
{
type: 'LABEL_DETECTION', // ラベルの検出
maxResults: 5
},
{
type: 'TEXT_DETECTION', // 文字の検出
maxResults: 5
},
{
type: 'LANDMARK_DETECTION', // 場所の検出
maxResults: 5
},
{
type: 'LOGO_DETECTION', // ロゴ検出
maxResults: 5
},
],
}]
})
};
let response = UrlFetchApp.fetch(url, options);
return JSON.parse(response.getContentText('UTF-8'));
}
/**
* LINEからコンテンツを取得する
* @param {String} messageId メッセージID
*/
function getLineContent(messageId) {
let url = `https://api.line.me/v2/bot/message/${messageId}/content`;
let options = {
'method': 'get',
'headers': {
'Content-Type': 'application/json; charset=UTF-8',
'Authorization': `Bearer ${LINE_CHANNEL_TOKEN}`
}
};
return UrlFetchApp.fetch(url, options);
}
-
execute
関数では、LINE Messaging APIからの通知内容により、処理を振り分けしています。message
の場合は、メッセージの内容を解析します。 -
getLineContent
関数でLINEに入力された画像を取得して、getAnnotate
関数でGoogle Cloud Vision APIに画像を送信します。検出できる内容はこちら。 - 検出した内容ごとにメッセージを作成して
sendLineReply
関数でLINE Messaging APIにPOSTします。
参考リンク
- 【Rails】Cloud Vision APIを用いて画像解析し、過激な画像を検知する方法
- LINE BOTからAWS Lambda介してGoogle Cloud Vision APIを呼ぶPython
- LINE APIが公開されたのでGoogle Cloud Vision使って画像解析しちゃうBOTをAWS Lambdaで作ってみた話
- Python+Cloud Vision APIでOCR、Bounding Boxまで!
- 【初心者向け】【Ruby】Google画像認識で、APIの叩き方を学ぶ
さいごに
ソースコードをGitHubに公開しています。
以上です。