10
5

More than 3 years have passed since last update.

[2−1]作成したQRコードを読み取り識別する

Last updated at Posted at 2019-12-30

この記事は"QRコードを使った入場システムを自作する"シリーズの記事です。

前回

"[1]独自のフォーマットに基づいてQRコードを発行する"では独自のフォーマットのQRコードを発行してデータベースに登録することができました。
今回はデータベースに登録したQRコードの読み取り方です。

QRコードを読み取るには

スキャナーを用意する予算がなかったのiOSアプリのPythonista3を利用してQRコードを読み取ります。

手順

Pythonista3を利用しなくてもなんでも読み取った後の処理は同じです。

  • QRコードをスキャン
  • 読み取ったコードを文字列に変換
  • MySQLで検索をかける

Pythonista3でQRコードを読み取る方法

今回一番きつかったのがこの部分で、objective-cをPython上で動かさなければいけませんでした。
Pythonistaには標準でobjc_utilというモジュールが入っているのでそれを利用します。

とは言っても...

objective-cなんか生まれてから一度も利用したことがなくswiftが主流?になってきているので今回はこちらを流用させていただいた。(一部改変)

ということで

以下がソースコードになる。

QRscanner1.py
# Barcode scanner demo for Pythonista

from objc_util import *
from ctypes import c_void_p
import mysql.connector as testdb
import ui
import sound


found_codes = set()
main_view = None

AVCaptureSession = ObjCClass('AVCaptureSession')
AVCaptureDevice = ObjCClass('AVCaptureDevice')
AVCaptureDeviceInput = ObjCClass('AVCaptureDeviceInput')
AVCaptureMetadataOutput = ObjCClass('AVCaptureMetadataOutput')
AVCaptureVideoPreviewLayer = ObjCClass('AVCaptureVideoPreviewLayer')
dispatch_get_current_queue = c.dispatch_get_current_queue
dispatch_get_current_queue.restype = c_void_p

#QRコードの読み取り
def captureOutput_didOutputMetadataObjects_fromConnection_(_self, _cmd, _output, _metadata_objects, _conn):
    objects = ObjCInstance(_metadata_objects)
    for obj in objects:
        s = str(obj.stringValue())
        if s not in found_codes:
            found_codes.add(s)
    #読み取り終了後にWindowを閉じる。
    main_view.close()

MetadataDelegate = create_objc_class('MetadataDelegate', methods=[captureOutput_didOutputMetadataObjects_fromConnection_], protocols=['AVCaptureMetadataOutputObjectsDelegate'])

@on_main_thread
def main():
    global main_view
    delegate = MetadataDelegate.new()
    main_view = ui.View(frame=(0, 0, 400, 400))
    main_view.name = 'Barcode Scanner'
    session = AVCaptureSession.alloc().init()
    device = AVCaptureDevice.defaultDeviceWithMediaType_('vide')
    _input = AVCaptureDeviceInput.deviceInputWithDevice_error_(device, None)
    if _input:
        session.addInput_(_input)
    else:
        print('Failed to create input')
        return
    output = AVCaptureMetadataOutput.alloc().init()
    queue = ObjCInstance(dispatch_get_current_queue())
    output.setMetadataObjectsDelegate_queue_(delegate, queue)
    session.addOutput_(output)
    output.setMetadataObjectTypes_(output.availableMetadataObjectTypes())
    prev_layer = AVCaptureVideoPreviewLayer.layerWithSession_(session)
    prev_layer.frame = ObjCInstance(main_view).bounds()
    prev_layer.setVideoGravity_('AVLayerVideoGravityResizeAspectFill')
    ObjCInstance(main_view).layer().addSublayer_(prev_layer)
    session.startRunning()
    main_view.present('sheet')
    main_view.wait_modal()
    session.stopRunning()
    delegate.release()
    session.release()
    output.release()
    #QRコードを読み取った際の処理
    if found_codes:
        #cur = conn.cursor()

        scan_code = str(''.join(found_codes))

        #table: QRidのデータを照合
        table = 'QRid'
        cur.execute("select * from QRid where QR=%s",(scan_code,))

        result = cur.fetchall()

        if len(result) == 0:
            sound.play_effect('digital:PhaserUp4')
            print('該当するデータがありません。')
            vibrate([50,0,50,0,50,0,50])

        else:
            sound.play_effect('arcade:Coin_5')
            print('ID'+'{:>15}'.format('DATE')+'{:>11}'.format('TIME'))
            for i in result:
                print(*i)


if __name__ == '__main__':
    #MySQLへ接続
    conn = testdb.connect(
        user = 'test', 
        password = '12345', 
        host = '192.168.x.x',
        port = '3306',
        database='QRtest'
    )

    #接続ステータスを確認
    conn.ping(reconnect=True)
    print('[Status] ', end='')
    print(conn.is_connected())

    cur = conn.cursor()

    main()

    #MySQLへの接続を終了
    cur.close()
    conn.commit()
    conn.close()

スクリプトを走らせるとカメラウィンドウが表示されます。
IMG_4029.PNG
正常に読み取られるとこのウィンドウが閉じてコンソールが開きます。
IMG_4028.PNG
MySQL上に登録されている情報が表示されれば成功です。
スクリーンショット 2019-12-30 15.05.38.png

次回予告

[2-2]作成したQRコードを読み取り識別する。でよりわかりやすいGUIを追加します。読み取り機は次回で完成です。
IMG_3969.PNG

10
5
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
10
5