画像認識できるチャットボットをGoogle Vision APIとLINE BOTで作る

LINEされた画像を認識するチャットボットの作り方についてまとめました。

チャットボットはLINE BOTとCloud Vision APIを連携させて作ります。

 

最終的にはこのような画像認識できるBOTを作成します。

 

 

 

 

Cloud Vision APIとLINE BOTとの連携イメージ

 

Cloud Vision API利用設定手順

 

 

注意
Cloud Vision APIは無料枠はありますが、どれだけ使っても無料という訳ではありませんので注意してください。

料金表は一度確認しておくことをオススメします。

Cloud Vision API料金

 

 

Cloud Vision APIが利用できるまでの設定としては以下を行います。

  • Googleアカウント作成
  • プロジェクトの作成
  • Cloud Vision API の有効化

 

1.Googleアカウント作成

Googleアカウントの作成ページからアカウントを作成してください。

 

2.プロジェクトの作成

以下のプロジェクト作成手順を参考にプロジェクトを作成してください。

【Google API入門(1)】Google OAuthでAccess Tokenを取得してみる

 

3.Vision APIの有効化

Cloud Vision APIページを開きます。

 

無料トライアルを選択します。

 

 

入力項目を埋めて先に進みます。

 

 

 

 

Google Cloud Platformの設定が完了したら、

Cloud Vision APIを検索して選択します。

 

 

Cloud Vision APIを有効にします。

 

認証情報を作成します。

 

 

APIキーで認証情報を作成します。

 

 

APIキーを控えておいてください。

Cloud Vision APIをコールする際のパラメータとして利用します。

 

 

必須ではありませんが、キーを制限する場合は、

特定のサイトやIPからのみAPIがコールできる設定も行えます。

 

 

Herokuの設定とPHPプログラミング

 

Herokuの設定は以下を参考に行ってください。

HerokuとLINE BOTでチャットボットを作る

 

ソースはGitHubからダウンロードしてください。

 

Cloud Vision APIで発行したAPIキー、LINE BOTで発行したアクセストークンの設定を行い、Heroku GitにソースをPUSHすれば、画像認識BOTの動作が確認できます。

 

 

 

プログラムの解説

まず、LINEで画像がアップロードされた際の動きのイメージを絵にするとこんな感じです。

 

 

main.php

LINEの画像が送信されるとLINE BOT APIからWebhook送信でmain.phpがコールされます。

main.phpはメインロジックが記載されているhello2.phpと、共通処理が記載されているtool.phpを読み込み、

LINE BOT APIから送信されたパラメータを引数としてhello2.phpのbot処理をコールします。

 

main.php
<?php

require_once('hello/hello2.php');
//require_once('vision/call.php');

define('DEBUG', 'debug.txt');
require_once('tool.php');

$input=file_get_contents('php://input');
debug('input', $input);

if (!empty($input)) {
	$events=json_decode($input)->events;
	foreach ($events as $event) {
		bot($event);
	}
}

 

 

hello2.php

メイン処理が記載されているのがhello2.phpです。

まず、メッセージIDを取得してLINEで送信されたバイナリを取得します。

バイナリを引数に画像認識処理をコールして認識結果(英語)を取得し、

それを翻訳処理をコールして英語から日本語に翻訳して結果を返信しています。

 

hello/hello2.php
<?php

function bot($event) {

	//画像ファイルのバイナリ取得
	$messageId = $event->{"message"}->{"id"};
	$ch = curl_init("https://api.line.me/v2/bot/message/".$messageId."/content");
	curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
	curl_setopt($ch, CURLOPT_HTTPHEADER, array('Authorization: Bearer ' . TOKEN));
	curl_setopt($ch, CURLOPT_ENCODING, null);
	$result = curl_exec($ch);
	curl_close($ch);

	// 画像認識
	$recognizedText = imageRecognize($result);
	// 認識結果翻訳
	$translatedText = translate($recognizedText);
	reply($event, $translatedText);

}

 

 

tool.php

tool.phpは便利な共通処理を記載しています。ログ出力とか、外部のAPIを呼び出す処理とか・・・

 

ここには、Cloud Vision APIをコールする処理などを記載しています。

(Vision APIは英語で結果を返却してくるのでTranslate APIをコールする処理もついでに作りました)

 

tool.php

<?php

define('TOKEN', '取得したトークン');
define('API_KEY','取得したAPIキー');

if (file_exists(DEBUG)) unlink(DEBUG);

function debug($title, $text) {
	file_put_contents(DEBUG, '['.$title.']'."\n".$text."\n\n", FILE_APPEND);
}

function heroku_debug($text) {
	$stdout= fopen( 'php://stdout', 'w' );
	fwrite( $stdout, "[DEBUG]={$text}\n" );
}

function post($url, $object) {
	$json=json_encode($object);
	debug('output', $json);

	$curl=curl_init('https://api.line.me/v2/bot/message/'.$url);
	curl_setopt($curl, CURLOPT_POST, TRUE);
	curl_setopt($curl, CURLOPT_POSTFIELDS, $json);
	curl_setopt($curl, CURLOPT_HTTPHEADER, [
		'Content-Type: application/json',
		'Authorization: Bearer '.TOKEN
	]);

	$result=curl_exec($curl);
	debug('result', $result);

	curl_close($curl);
}

function reply($event, $text) {
	$object=[
		'replyToken'=>$event->replyToken,
		'messages'=>[['type'=>'text', 'text'=>$text]]
	];
	post('reply', $object);
}

function reply_image($event, $original, $preview) {
	$object=[
		'replyToken'=>$event->replyToken,
		'messages'=>[[
			'type'=>'image',
			'originalContentUrl'=>$original,
			'previewImageUrl'=>$preview
		]]
	];
	post('reply', $object);
}

function push($to, $text) {
	$object=[
		'to'=>$to,
		'messages'=>[['type'=>'text', 'text'=>$text]]
	];
	post('push', $object);
}

function load($file) {
	$json=file_get_contents($file);
	return json_decode($json);
}

function save($file, $object) {
	$json=json_encode($object);
	file_put_contents($file, $json);
}

function lock($file) {
	$fp=fopen($file, 'c');
	flock($fp, LOCK_EX);
	return $fp;
}

function unlock($fp) {
	flock($fp, LOCK_UN);
	fclose($fp);
}

// 翻訳(英語→日本語)処理
function translate($text) {
	$handle = curl_init();

	if (FALSE === $handle)
	   throw new Exception('failed to initialize');

	curl_setopt($handle, CURLOPT_URL,'https://www.googleapis.com/language/translate/v2');
	curl_setopt($handle, CURLOPT_RETURNTRANSFER, 1);
	curl_setopt($handle, CURLOPT_SSL_VERIFYPEER, false);
	curl_setopt($handle, CURLOPT_POSTFIELDS, array('key'=> API_KEY, 'q' => $text, 'source' => 'en', 'target' => 'ja'));
	curl_setopt($handle,CURLOPT_HTTPHEADER,array('X-HTTP-Method-Override: GET'));
	$json = curl_exec($handle);
	$array_json = json_decode($json, true);
	$translated = $array_json["data"]["translations"]["0"]["translatedText"];
	print($translated);
	return $translated;
}

// 画像認識処理
function imageRecognize($image) {
	// リクエスト用のJSONを作成
	$json = json_encode( array(
		"requests" => array(
			array(
				"image" => array(
					"content" => base64_encode($image) ,
				) ,
				"features" => array(
					// array(
					// 	"type" => "FACE_DETECTION" ,
					// 	"maxResults" => 3 ,
					// ) ,
					// array(
					// 	"type" => "LANDMARK_DETECTION" ,
					// 	"maxResults" => 3 ,
					// ) ,
					// array(
					// 	"type" => "LOGO_DETECTION" ,
					// 	"maxResults" => 3 ,
					// ) ,
					// array(
					// 	"type" => "LABEL_DETECTION" ,
					// 	"maxResults" => 3 ,
					// ) ,
					// array(
					// 	"type" => "TEXT_DETECTION" ,
					// 	"maxResults" => 3 ,
					// ) ,
					// array(
					// 	"type" => "SAFE_SEARCH_DETECTION" ,
					// 	"maxResults" => 3 ,
					// ) ,
					// array(
					// 	"type" => "IMAGE_PROPERTIES" ,
					// 	"maxResults" => 3 ,
					// ) ,
	        array(
	          "type" => "WEB_DETECTION" ,
	          "maxResults" => 1 ,
	        ) ,
				) ,
			) ,
		) ,
	) ) ;

	$curl = curl_init() ;
	curl_setopt( $curl, CURLOPT_URL, "https://vision.googleapis.com/v1/images:annotate?key=" . API_KEY ) ;
	curl_setopt( $curl, CURLOPT_HEADER, true ) ;
	curl_setopt( $curl, CURLOPT_CUSTOMREQUEST, "POST" ) ;
	curl_setopt( $curl, CURLOPT_HTTPHEADER, array( "Content-Type: application/json" ) ) ;
	curl_setopt( $curl, CURLOPT_SSL_VERIFYPEER, false ) ;
	curl_setopt( $curl, CURLOPT_RETURNTRANSFER, true ) ;
	if( isset($referer) && !empty($referer) ) curl_setopt( $curl, CURLOPT_REFERER, $referer ) ;
	curl_setopt( $curl, CURLOPT_TIMEOUT, 15 ) ;
	curl_setopt( $curl, CURLOPT_POSTFIELDS, $json ) ;
	$res1 = curl_exec( $curl ) ;
	$res2 = curl_getinfo( $curl ) ;
	curl_close( $curl ) ;

	// 取得したデータ
	$json = substr( $res1, $res2["header_size"] ) ;
	heroku_debug($json);
	$array_json=json_decode($json, true);
	$text=$array_json["responses"]["0"]["webDetection"]["webEntities"]["0"]["description"];
	print($text);
	return $text;
}

 

プログラム自体はそれほど難しいものではなく、ただAPIを呼び出しているだけです。

それよりもHerokuやCloud Vision APIの設定などの方が難しく感じたかも知れません、、、

 

 

 

ということで、今回はLINE BOTで画像認識させてみました。

 

画像認識の知識がなくても、APIを組み合わせるだけでカレーや寿司の画像の識別ができました。

これを応用して、面白いモノを作ってみてください。

 

コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です

このサイトはスパムを低減するために Akismet を使っています。コメントデータの処理方法の詳細はこちらをご覧ください