QRコードのディスプレイ表示


バージョン
NAOqi 2.5.5.5
Choregraphe 2.5.5.5

この記事の内容

 本記事では、PepperにQRコードを読み込ませ、読取結果をディスプレイに表示させるサンプルアプリを紹介します。

QRコード読み込み・表示アプリ

サンプルアプリ

 サンプルプログラムはGitHubよりダウンロードしてください。
 https://github.com/Atelier-Akihabara/pepper-qrio-example

 サンプルプログラムqr_io_appを実行しQRコードを認識すると以下のように表示されます。(qr_io_app.pmlを開いてプログラムをPepperに転送してください)

サンプルアプリの基本動作

  • PepperにQRコードをかざす。
  • QRコードを認識すると、ディスプレイに認識したQRコードと同じ内容のQRコードが表示される。QRコードの仕様上、かざしたQRコードと表示されたQRコード画像が図形的に必ずしも一致するわけではありません。
  • バックバンパーを押すと終了する。

解説

 処理の流れは、1. 初期化→2. 画像化→3. 表示となります。

1. 初期化

SetPathLibFldボックス

 libフォルダにパスを通し、アプリがlibフォルダのライブラリを使えるようにします詳細については次の記事を参照してください(拡張ライブラリの組み込み方法)。libフォルダにはQRコードライブラリqrcodeがインストールされています。

Initializeボックス

 ディスプレイを有効化し、PepperのBasic Awarenessを停止させ、顔を前向きにする基本的な初期化行います。

2. 画像化

 PepperがQRコードを認識すると、ALMemoryから認識結果がボックスに飛んできます。
 ALMemoryからQRコード文字列を受け取るとReadWrite QRボックスは文字列を画像に変換し、ALMemory経由でディスプレイに画像データDataUriを送信します。

ReadWrite QRボックス

 本プログラムの中心的役割を担うボックスです。処理の内容をみていきます。

処理のメインコード

  1. 受け取った文字列pを画像化関数makeQRに渡します。
  2. makeQR関数で変換された画像データをconvertToDataUriに渡しDataUri化します。
  3. raiseEventでDataUri化されたデータをディスプレイに送信します。
def onInput_QRinput(self, p):
    #QR検知中確認
    if not self.isDetecting :
        return
    #検知開始後、初回のみ実行
    self.isDetecting = False
    #読み取ったQRコードの文字列を取得
    inputCode = p[0][0]
    #QR生成
    img = self.makeQR(inputCode) # 1.
    #ファイルオブジェクト化
    s = StringIO.StringIO()
    img.save(s, "png")
    #画像をdataURIスキームに変換
    dataUri = self.convertToDataUri(s.getvalue()) # 2.
    s.close()
    #タブレットに送信
    self.memory.raiseEvent(self.getParameter("key"), [inputCode, dataUri]) # 3.
    #一定時間待機
    time.sleep(2)
    #QR検知再開
    self.isDetecting = True

 続いて、makeQR内で呼び出されているサブルーチンについて解説いたします。

画像生成コード

  1. ライブラリqrcodeを利用しQRコードライブラリに画像作成のためのパラメータを設定します。
  2. QRコード画像生成を実行します。
  3. 画像を目的のサイズにリサイズします。
def makeQR(self, str):
    #QR生成
    import qrcode
    #エラー訂正レベル
    ec_level = [qrcode.constants.ERROR_CORRECT_L,    # 7%以下の誤差を修正
                qrcode.constants.ERROR_CORRECT_M,    #15%以下の誤差を修正
                qrcode.constants.ERROR_CORRECT_Q,    #25%以下の誤差を修正
                qrcode.constants.ERROR_CORRECT_H]    #30%以下の誤差を修正
    qr = qrcode.QRCode(
        #QRコードのバージョン
        version=self.getParameter("version"),
        #エラー訂正レベル
        error_correction=ec_level[self.getParameter("error_correction")],
        #セルサイズ設定
        box_size=self.getParameter("box_size"),
        #境界線のサイズ設定
        border=self.getParameter("border")
    ) # 1., 2.
    qr.add_data(str)
    qr.make(fit=True)
    img = qr.make_image()
    #リサイズ
    imgSize = self.getParameter("imgSize")
    img = img.resize((imgSize, imgSize)) # 3.
    return img

DataUrl変換コード

 画像データをDataUriに変換するメンバメソッドです。onInput_QRinput内で利用しています。

def convertToDataUri(self, img):
    #画像をdataURIスキームに変換
    img_b64 = img.encode("base64").replace("\n", "")
    dataUri = 'data:image/png;base64,{0}'.format(img_b64)
    return dataUri

ReadWrite QRボックスのパラメータ

 参考までにパラメータの設定内容を解説いたします。下記のパラメータは上記コード内のself.getParameterにて取得されています。

バラメータ 内容
key 認識データの送信先です。認識されたデータは、ALMemoryにDataUri形式で送信されます。
version QRコードの型番を指定します。型番は1〜40まであり、データサイズが増えるに従い大きくする必要があります。詳細については、QRコードの規格を参照しください。
error_correction QRコードのデータ訂正コード比率を4段階で設定します。エラー訂正比率が高ければ、信頼性は高くなりますが、保存できるデータ容量は少なくなります。
- 0 ERROR_CORRECT_L7%まで
- 1 ERROR_CORRECT_M15%まで
- 2 ERROR_CORRECT_Q25%まで
- 3 ERROR_CORRECT_H30%まで
box_size ピクセルの構成数を設定します。
border 境界線のサイズを設定します。
imgSize 生成されたデータの目標サイズですこのサイズにリサイズされます

3. 表示

 ALMemoryに飛んできたデータを受け取りディスプレイに画像データを表示します。

HTMLコード

 画像を表示するためのスペース箱 id="qr_display" を用意しています。中にはテキストを表示するための

要素と画像を表示するための要素を記述しています。

<!DOCTYPE html>
<html lang="ja">
  <head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width,initial-scale=1.0,minimum-scale=1.0,maximum-scale=1.0,user-scalable=no">

    <title>no title</title>

    <link rel="stylesheet" href="css/normalize.css" type="text/css" />
    <link rel="stylesheet" href="css/main.css" type="text/css" />
    <script src="/libs/qimessaging/2/qimessaging.js"></script>
    <script src="js/jquery-3.0.0.min.js"></script>
    <script src="js/adjust23.js"></script>
    <script src="js/main.js"></script>
  </head>
  <body>
    <div id="qr_display">
      <p></p>
      <img src="">
    </div>
  </body>
</html>

JavaScriptコード

  1. ALMemoryキー "qr_io_app/toTablet_sendQR" を受け取るサブスクラバを作成します。
  2. ALMemoryからデータを受け取るとHTML側に用意した画像を表示するためのスペース箱 id="qr_display" 内の<p>要素と<img>要素にデータを書き込みます。
$(function(){
    QiSession(function( s ) {
        session = s;
        session.service("ALMemory").then(function (ALMemory) {
            //待受け
            ALMemory.subscriber("qr_io_app/toTablet_sendQR").then(function(subscriber) {
                subscriber.signal.connect(displayQR);
            });

            //QR表示画面
            function displayQR(value) {
                $("#qr_display p").text(""+value[0]+"");
                if (value[0] == null) {
                    $("#qr_display p").text("「None」");
                }
                $("#qr_display img").attr("src", value[1]);
            }
        });
    });
});

活用例

 本サンプルでは掲載してませんが、アプリにカメラプレビューを搭載し、読み取った結果をQRコード画像にしてディスプレイに表示させることもできます。
 また、利用者がPepperにQRコードをかざし、読み取った結果をもとにPepperが次のトリガーとなるQRコードを表示する使い方も考えられます。

 例えば、展示会場では次のような動作ができるのではないでしょうか。

  1. 展示会場等で入り口のPepperに入場用のQRコードをかざす
  2. Pepperに入場者の情報使った固有のQRコードが表示される
  3. 入場者は表示されたQRコードを読み取る
  4. 展示の説明とともに、次の順路を案内するまたは、次の場所にいるPepperに誘導する等

 QRコードは応用範囲が広いため、プレビュー・表示のテクニックを駆使したアプリ開発に挑戦してみてください。

記事協力企業株式会社システナ