2
Help us understand the problem. What are the problem?

posted at

updated at

Organization

チラシを撮って、オンラインサイトに飛びます!

1.概要

 チラシとWEBサイトの連携企画(チラシ掲載の商品がオンラインでも買えたり予約できる)において、チラシの商品部分を写真に撮って、Line-botに投稿することで、オンラインサイトの該当商品ページへのリンクを表示させ、すぐに購入してもらえるようにします。

2.動作の様子

3.制作の動機

 GoogleのTeachable Machineという機械学習システムのことを学んだので、なにか自分の業務に応用できないかとTeachable Machineを出発点とした課題の設定と解決を試みました。

 Teachable Machine(以下、T.M.と略します。)の持つ学習機能を縦に、自分の業務を横に書き出し、使えそうなところは無いかを検討した表です。

機能\業務 チラシ カタログ 数値実績 メール処理 日常業務
画像
音声
ポーズ

詳細はこちらにも投稿

 チラシ・カタログは商品画像が沢山あるので、何かできないかと考えた結果、
商品画像を送ることで、何らかの結果が返ってくるモデルが一番良いと考えました。
思いついたパターンは、二つ。
  1.チラシの商品画像を学習させ、チラシの商品画像を送ることで、詳しい商品情報が得られるツール。
  2.チラシの商品画像を学習させ、チラシの商品画像を送ることで、WEBサイトの商品ページに飛ぶツール。
 2.については、最近は某R社さんでも、カタログにQRコードを載せて、WEBサイトに誘導するというパターンを時々やっておられます。image.png
 ただし、これをやると、紙面上にQRコードが並び、少々見苦しいデザインになってしまいます。
ふと、周りを見回すと丁度、某T社オンラインサイトと連動したチラシが目に止まりました。
 この瞬間に、今回の課題が決まりました。QRコードを使わずに、同じことが出来るかもしれない。

 QRコードは株式会社デンソーウェーブの登録商標です。

4.制作のツボ

1.今回使用したサービス・ツール

   Teachable Machine:Googleの提供する機械学習サービス
   Node-Red:IBM社が開発したビジュアルプログラミング開発ツール
   heroku:Node-Redを走らせるための無料でも使えるクラウドサービス(Paas)
   SSS API:GoogleSheetsの表をAPI化し、検索できる。書き込みは不可。

2.標準ではないNode-Redのノード

完成後も使用し続けるもの

  node-red-contrib-teachable-machine:T.M.とデータをやり取りするためのノード
  node-red-contrib-line-messaging-api:Line-botとして機能させるためのノード

製作中は、必要だが、完成後はなくてもよいもの

  node-red-contrib-image-output:製作中、入力した画像をモニタするために使用。
  node-red-contrib-browser-utils:製作中PCのWEBカメラの画像を入力に使うためのノード

試したが、最終的には使わなかったもの

  node-red-contrib-line-image-api:Lineからの画像を取り込むために試したノード
  node-red-contrib-publicgooglesheets:GoogleSheetsに読み書きするノード。VlookUP関数的な使用ができない。

今回使用したサービス・ツールは、現在のところすべて無料で使用可能です。
事前に登録が必要なものが多いですが、登録の仕方については、今回は触れません。

3.概念図とNode-Red全体図

データの流れを示した概念図です。
image.png
次にNode-Redに配置したノードの全体図を示します。
沢山のノードが並んでいますが、完成後の動作に必要なのは、番号付きの吹き出しの付いたノードだけです。薄緑のmsgで始まるノードは、すべて作成中にどんなメッセージが流れているか確認するために使用したもので、完成後は削除しても動作します。
image.png

4.各ノードの設定

 上記全体図の吹き出しの番号順に内容を説明します。

①webhook

設定の中身は、これだけです。
image.png
 しかし、これにだどりつくまでかなりの時間を要しました。
ここでは、概念図を示したように、ここではLineから送られてくるメッセージの最初の受け取り口を設定するはずです。

Webhookノードの設定は、URLのパス部分(ホスト名のうしろのスラッシュ移行)を指定するだけです。引用元

 さらっと、書いてあるのが、何を示しているのかピンときませんでした。
node-redを編集しているページの最後の数列を入力してみたりして、時間を浪費しましたが、
いろいろ試した結果、実はなんでもよいことが判りました。
重要なのは、スラッシュで始まる自分の決めたフォルダの名前で、その名前をLine側に設定してやることで、Lineからのデータが受信できるようになるわけです。
あえて、何でもよいことを示す意味で名前を設定しています。

 次に今決めたフォルダの名前(Path)をLine側に設定します。
Line Developersサイトにて、Messaging API設定を開きます。
設定項目の中のWebhook URLというところに設定します。
image.png
黒四角のところは、herokuのアカウントIDが入ります。
編集中のNode-RedのURLをみるとこんな風になっています。

https://node-red-■■■■.herokuapp.com/red/#flow/123456789012345

red以降を削除して、先ほどのPathの文字列を付け足したアドレスが、Lineからの受け口ということになります。

②http request

 ここも難しかったのですが、重要です。ここでは、Lineから送られてきたメッセージの内容より、
画像が保存されているURLを指定して、画像のデータを貰うための設定を行います。

Node-Red側の設定に先立って、Line Official Account Managerの設定で、アカウント設定の内容を確認します。
image.png
Botの製作をやっていると、写真や動画の受け取りを「受け取らない」に設定しがちですが、
今回は画像の送受信ができないと困るからです。

http requestの設定内容です。
image.png

・メソッド:今回は、Line側に画像データを要求するので、「GET」です。
・URL:中身は、次のようになります。

https://api-data.line.me/v2/bot/message/{{{line.event.message.id}}}/content

 Lineのメッセージは、画像などの大きいデータを直接送らず、代わりにデータを保持しているIDを埋め込んでいるそうです。ここでは、画像のありかとしてのURLアドレスをもとめデータを取得し、次のT.M.にデータを送ります。

 画像のありかを示すURLは、次になります。(リンクをクリックするとLineDeveのマニュアルに飛びます。)

 https://api-data.line.me/v2/bot/message/{messageId}/content

 では、画像を示す[messageId]は、どこにあるでしょうか?
 その手掛かりが、一番目のDebugノードがデバッグウィンドウに吐き出す内容に隠れています。
Debugノードの設定は、
image.png
 そして、実際に吐き出しているメッセージです。
image.png
 ドリルダウンしてidを見つけました。ただしこの数字は、1回限りのものなので、パスをコピーという部分をクリックして、このidが、[line.event.message.id]という中にしまわれていることが判ります。
 先ほどの、画像のありかを示すURLの{messageId}という部分と置き換えた文字列が、URLの設定すべき内容となります。

・ペイロード:データ本体を意味し、通常は、メッセージの本文などが格納されていますが、今回は、上の画像にも写っているように、"(media)" 画像や動画の類であることの区分が入っているだけなので、「無視」します。

・認証:Lineから、T.M.が画像のデータを貰うためには、認証が必要です。
Line-botを作るときにお約束のように出てくるチャンネルアクセストークンの出番です。
トークンを使用する一般的な認証の名前が「Bearer認証」で、Line-DevelopersのMessaging API設定から、チャンネルアクセストークンをコピーして貼り付けます。
image.png

・出力形式:T.M.に送る画像の形式を指定します。バイナリバッファです。

③teachable machine

 いよいよ、ここでT.M.に対して画像のデータ送ります。
 説明の都合上、ここに至ってやっとTeachable Machineの本体に触れますが、実際には、先に学習モデルを用意していました。
 学習モデルを三つだけに絞り、うまく画像を認識して、判別していることが分かってから、Line-botとして仕立てるための作業を始めたのが、現実の流れです。実は、最初、チラシのコマは小さくて複雑なので、判別できないかもしれないと疑っていました。最初に作ったモデルは、大きめの3コマのデータで学習させ、ほぼ100%識別できていたので、制作を開始しました。完成後に学習モデルを21アイテムに増やしました。
 T.M.の使い方は、むしろ簡単です。モデルの学習のさせ方は奥が深そうですが、使い方はすぐに理解できると思います。
 リンク先のT.M.に飛び、「使ってみる」→「新しいプロジェクトから画像プロジェクト」を選びます。
 ここでは、Classに商品のカタログ番号を付け、各商品のチラシ画像を5~6枚づつ登録しました。
注意した点は、出来るだけ商品を画像の真ん中に置くこと。ピントが合うできるだけ近くで撮った画像。少しだけ離れた画像、右左に少し傾けて撮った画像などを入れるようにしました。

  実際に登録しトレーニングさせた画面
image.png
今回は、某T社さんのチラシのWEB連動企画の所から、21品目を選んでいます。
後は、「モデルをエクスポート」するをクリックして、「モデルをアップロード」を選びます。
少し待って、「共有可能なリンク」が、表示されますので、そのURLをノードに設定します。(下画像 緑枠)
image.png
Mode:Online
Output:今回は、最有力候補を一つだけ返してくれればよいので、「Best predition」を選びます。

④template

 ここでは、T.M.からの返事を次のGoogle sheetsのデータから情報を取り出すための準備をします。
③のT.M.からのメッセージの内容をデバッグウィンドウで確認します。
image.png
 内容が、配列になっており、A013というカタログ番号と0.66038・・・・という、確度が入っています。
 今回必要なのは、カタログ番号だけですので、パスをコピーしてデータが「payload[0].class」の中に入っていることを得ます。
templateの中身は下の赤線部分だけ、設定します。これにより、メッセージの本文がカタログ番号だけに変更されます。
image.png

⑤http request

 ここでは、予めGoogle Sheetsに下のような、カタログ番号と、WEBサイトのURLの表を作成しておき、T.M.から貰ったカタログ番号で引くという働きをします。
image.png

 GoogleSheetsから、データを引くのに、最初Node-Redの外部ノードを検索して引っかかったのが、これでした。
image.png
 しかし、用意されている機能が、セルの値の読み出し・書き出し・行の追加・削除の4つしかありませんでした。JavaScripitで処理する覚悟であればこれでもよいのでしょうが、ExcelのVlookUP関数のごとく、お手軽に検索結果を返してほしいと思いました。
 色々調べて、たどり着いたのが、SSS APIでした。
日本語化されたサイトで、1件だけのデータも取得できます。(ただしSheet側に情報を書き込むことが出来ないので、用途によっては不向きです。)

https://api.sssapi.app/<"SSS API_ID">/<"sheetの一番左の列の値">

をhttp requestノードに設定すればよいのですが、最後の<"sheetの一番左の列の値">の入れ方が判らなくて、
時間を浪費しました。結局教えていただいたのですが、Payloadを三重の{}でくるんでURLに付け足すというシンプルな手段で解決できました。
image.png
緑枠の中身は、https://api.sssapi.app/<"SSS API_ID">/{{{payload}}} となっています。

⑥split

 SSS APIからの返事が、求めるSheetのB列のURLだけなら、楽だったのですが、次の画像のように検索に使ったカタログNoとURLの1行分のデータが戻ってきています。
image.png
 そこで、カタログNoとURLを分けるために使っています。
設定は特になく、初期設定のままです。
image.png
 これにより、次の出力へ変化します。二つに分かれています。
image.png

⑦swith

 ここでは、二つに分けたメッセージを内容によって、3つに分けています。
1番目は、正しくURLを返してきた場合のデータ :「https」という単語が含まれる場合
2番目は、WEBの取り扱いがない商品だった場合のデータ:「WEB」という単語が含まれる場合
3番目は、もはや不要になったカタログ番号のデータ:その他
image.png

⑧template

 ここでは、URLが含まれている場合のリプライメッセージを成形します。
image.png

⑨template

 ここでは、WEBの取り扱いがない場合のリプライメッセージを成形するつもりでしたが、
流れてくるデータのままでよかったので、必要のないノードでした。
image.png

 因みに、3番目のカタログNoのデータは分岐した後、必要ないのでデバッグウィンドウに表示させていますが、本線から離脱です。

⑩ReplyMessage

 いよいよ最後です。ここで、Line側に最終の返信メッセージを送信するための設定です。
個々での設定は、Line Developersのサイトから、自分のアカウントの値を拾ってきて貼り付けるだけです。
Secret:チャンネル基本設定にある、「チャンネルシークレット」の値です。
AccessToken:Messaging API設定にある、「チャンネルアクセストークン」の値を貼り付けます。
image.png

 これにて完成です。お疲れさまでした。本当に疲れたよ((+_+))

##5.感想と反省
 Node-Redは、初心者にはとっつきにくい仕組みですが、JavaScriptを学べは、非常にパワフルなツールなんだと思います。何でもないメッセージの処理や、引数の与え方など、自分には癖が強いように感じられ、参考記事を探しても、ここぞという部分が説明されていないことが多く難儀しました。その反動もあって、今回はできるだけ詳しく作り方を書いたつもりです。
 チラシやカタログの商品画像を撮って、商品を区別し何らかのサービスを提供するというパターンは、結構実務にも生かせるように思いましたので、部内のミィーティングで紹介してみたころ、真っ先に送った画像の判別を間違うことがないかを気にされました。
 実際、商品によっては、高い確率で別の商品として判別されてしまう学習モデルになってしまっています。完成後に、急遽、登録商品数を3アイテムから、21アイテムまで増やしたため、一部確度の低いデータが混ざってしまいました。原因として考えられることは、そもそも登録した画像が、1アイテムあたり5~6枚と少ないこと、チラシを右手に持って、左のスマホで撮影するという雑な手振れ画像を登録していること、室内の照明で撮影していますが、光の当たり方でも大きく変わることを無視しています。
 また、T.M.は、確度を返してきていますが、今回は確度を無視して、一番高いものを選ぶだけにとどまっています。本来ならば、60%以下の場合は、再度画像を撮影しなおしてくださいというメッセージを返すなどして、
対応すべきでした。画像以外のメッセージが入力された場合の処理なども端折って作っています。
 さらに、チラシ1コマに色違いなど複数の商品がある場合、現在は、とりあえず若いカタログ番号の商品を返すように、リストを作っていますが、どちらの商品にするか確認する対話形式の処理も必要かと思いました。
 改めて時間をとって、データの学習のさせ方と確度を研究したうえで、実用性があるのか判断したいと思います。
 画像を学習させるのは、実は、とても骨の折れる作業です。サンプルの画像を増やすとなると、一層困難になります。冗談ではなく、早くも、学習作業を簡単にするためのツールが必要なのでは無いかとなやみ始めました。

Register as a new user and use Qiita more conveniently

  1. You can follow users and tags
  2. you can stock useful information
  3. You can make editorial suggestions for articles
What you can do with signing up
2
Help us understand the problem. What are the problem?