今回はPicameraを使ったQRコードの認識アプリケーション作成し、そのアプリケーションの自動起動や監視、遠隔更新をisaaxで実現する方法について説明します。動作を確認するために必要なモノは下記の通りです (isaax勉強会ではあらかじめ用意したSDカードを使います)。

  • Raspberry Pi
  • microUSBの電源 5V2A
  • WiFiまたは有線LAN (3, Zero W以外のモデルはUSBドングルが必要です)
  • SDカード (4GB以上)

作成するアプリケーションの全体像はこちらから確認できます:

リポジトリを作成する

isaaxを使ってデプロイするアプリケーションの実体はgitリポジトリのソースコードです。そこではじめに、デバイスに配信するアプリケーションを用意します。GitHubにログインして、右上の「+」ボタンから新しいリポジトリを作成しましょう。

「Initialize this repository with a README」にチェックを入れ、下図の内容で「Create repository」をクリックします。Repository nameDescriptionは任意です。

アプリケーションの実装

簡略化のために、GitHub上に直接ファイルを作成します(gitに使い慣れている方はお使いのPCにクローンしてお好きなエディタで編集して構いません)。「Create new file」をクリックするとエディタが開くのでそちらにコードを記述していきます。

ファイル名としてmain.pyを入力し、編集しやすいようにtabの設定などを変更します。

edit-settings.png

それでは、コーディングをしていきましょう。はじめに必要なモジュールをインポートします。

from flask import Flask, Response
from pyzbar import pyzbar
from picamera.array import PiRGBArray
from picamera import PiCamera
from datetime import datetime

import numpy as np
import cv2
import time

Picameraにアクセスするオブジェクトの作成と設定、Flask WEBサーバのインスタンス作成を行います。PiRGBArrayは、Picameraのキャプチャから3次元(高さ、幅、色)の配列を生成します。

...

camera = PiCamera()
camera.resolution = (640, 480)
camera.framerate = 32
rawCapture = PiRGBArray(camera, size=(640, 480))
time.sleep(0.5)

app = Flask(__name__)

Picameraの映像をMotion JPEGとしてブラウザから確認できるようにするためのエンドポイントを作成します。

...

@app.route('/stream')
def stream():
    return Response(gen(),
                    mimetype='multipart/x-mixed-replace; boundary=frame')

def gen():
    while True:
        frame = get_frame()
        yield (b'--frame\r\n'
           b'Content-Type: image/jpeg\r\n\r\n' + frame + b'\r\n\r\n')

get_frame関数を定義します。Picameraからフレームを読み込み、QR認識とその位置を描画する関数を呼び出しています。rawCapture.truncate(0)を行うことで現在読み込まれている画像配列を捨て、次にget_frame関数が呼び出された際にrawCaptureを再利用します。

... 

def get_frame():
    camera.capture(rawCapture, format="bgr", use_video_port=True)
    frame = rawCapture.array
    process_frame(frame)
    ret, jpeg = cv2.imencode('.jpg', frame)
    rawCapture.truncate(0)

    return jpeg.tobytes()

取得したフレームを使ってQR認識と認識したポジションの描画を行います。decode関数とdraw_positions関数はこのあと定義します。

...

def process_frame(frame):
    decoded_objs = decode(frame)
    draw_positions(frame, decoded_objs)

Pyzbarライブラリを使って実際にQRを認識するコードを記述します。

...

def decode(frame):
    decoded_objs = pyzbar.decode(frame, scan_locations=True)
    for obj in decoded_objs:
        print(datetime.now().strftime('%H:%M:%S.%f'))
        print('Type: ', obj.type)
        print('Data: ', obj.data)
        
    return decoded_objs

認識したQRコードの位置をフレームに描画する関数を作成します。

...

def draw_positions(frame, decoded_objs):
    for decoded_obj in decoded_objs:
        left, top, width, height = decoded_obj.rect
        frame = cv2.rectangle(frame,
                  (left, top),
                  (left + width, height + top),
                  (0, 255, 0), 2)

最後に、Flaskのサーバを立ち上げる処理を記述して完了です。

...

if __name__ == '__main__':
    app.run(host="0.0.0.0", debug=False, threaded=True)

main.pyの全体像はこちらから確認してください。エディターの下部にあるフォームからコミットメッセージを記入して「Commit new file」ボタンをクリックすることでファイルの作成を完了できます。

isaax.jsonの追加

isaaxを使ってデバイス上でアプリケーションを動かすために、アプリケーションのルートディレクトリにisaax.jsonという設定ファイルを作成します。先ほどと同じ手順で下記の内容のファイルを新しく作成します。

{
    "description": "QR reader sample",
    "scripts": {
        "start": "python3 -u main.py"
    }
}

startプロパティがアプリケーションの実行方法を指定しています。

isaaxプロジェクトの作成

isaax.ioにログインしましょう。お使いのGitHubアカウントを使ってログインすると簡単です。「+」新規プロジェクト追加ボタンをクリックしてプロジェクトを作成します。

モーダルが開くので下図のように詳細情報を入力します。レポジトリは今回作成したものを選択し、更新方法にはコミットを選択します(プロジェクト名、説明は任意)。

isaaxエージェントのインストール

作成したプロジェクトにデバイスを登録します。登録作業はRaspberry Piのターミナルにログインしてワンライナーのコマンドを実行するだけです。コマンドを実行することでisaaxエージェント(デバイス上でユーザーアプリケーションを監視するソフトウェア)とユーザーアプリケーションをインストールします。

先ほどプロジェクトを作成した時点で、下図のようなモーダルが表示されているはずです。下の方のコマンド「インストールスクリプト」がisaaxエージェントのインストールを行います。右下のボタンからクリップボードにコピーしてください。

Raspberry PiにSSHログインします。

ssh pi@<IP ADDRESS>

先ほどコピーしたコマンドを貼り付けて実行します。下図のようにISAAX Agent installation finishedが表示されれば成功です。

この時点で、GitHubで編集したアプリケーションも一緒にインストールされます。PCからブラウザを開き、<Raspberry PiのIPアドレス>:5000/streamにアクセスしてみましょう。Picameraの映像が確認できたら新しいブラウザのウィンドウを開き、下記のURLで表示されるQRコードを認識させてみましょう。

QRサンプル – QR Code Generator

緑色の枠が表示されていれば認識しています。

認識したQRコードのIDや上手くいかなかった場合のエラーログはisaaxダッシュボードの通知パネルから確認できます。ダッシュボードをリロードすると、さきほど登録したデバイスが表示されるのでクリックしてログを見てみましょう。

アプリケーションの更新

リポジトリにコミットを作成すると、アプリケーションの更新が自動的に行われます。

試しに、認識QRコードの枠の色を緑色から別の色に変更してみましょう。GitHubからmain.pyを開き、編集ボタンをクリックします。

エディタモードになるので、display関数のcv2.rectangle()に変更を加えます。第4引数の(0, 255, 0)はそれぞれBGR (RGBの順番ではありません) の値を0 ~ 255で表します。

...
frame = cv2.rectangle(frame,
                      (left, top),
              (left + width, height + top),
              (255, 0, 0), 2) # 青色に変更

...

変更を加えたらページ下部からコミットメッセージを記入し、「Commit changes」ボタンをクリックします。デバイスの更新に関するイベントは、アプリケーションのログと同様にisaaxのダッシュボードから確認できます。

ブラウザをリロードし、QRコードをもう1度かざしましょう。色が変更されていれば更新成功です。上手くいかない場合はisaaxのダッシュボードからエラーがないか確認します。

次のステップ

ハンズオンはここまでとなります。もし時間が余った場合は以下の内容にチャレンジしてみましょう。

 

課題1. 認識したQRコード数の表示

pyzbarのdecode関数は画像内にある複数のQRコードを認識します。OpenCVの関数、putTextメソッドを使って下図のように読み取ったQRコードの数を表示しましょう。

画像にテキストを追加 – cv2.putTextメソッド

 

課題2. QRコードのデータ表示

課題1と同様の方法でフレームに認識したQRコードのデータを描画してみましょう。

 

 

付録. OSの環境構築

このセクションでは今回のプログラムを動作させるために必要なライブラリなど、環境構築の手順を紹介します。

まずRaspbianがインストールされているmicroSDカードを準備します。
デスクトップ版でもライト版でも構いません。

準備ができたら以下のコマンドを実行し、必要なライブラリをインストールします。

sudo apt update -y
sudo apt upgrade -y
sudo apt update -y
sudo apt install -y python3-pip python3-dev libzbar-dev libatlas-base-dev libjasper-dev libgstreamer1.0-dev libavcodec-dev libavformat-dev libswscale-dev libqt4-dev 
sudo pip3 install numpy opencv-python picamera[array] pyzbar flask imutils

以上で環境構築は完了です。サンプルコードをデプロイして動作チェックしてみましょう。


Leave a Reply

Your email address will not be published. Required fields are marked *