Python3でQRコードを読み込みたかった

Python3でQRコードを読み取るためにPyPIからパッケージを探したのでメモ。

結論から言うとfastzbarlightが簡単かつ早く読み取りができます。

まえおき

C/C++QRコードやバーコードを読み取らせるライブラリとして有名そうなのはZbarで、公式でPythonのライブラリもありました。 ところがPython2.x用のパッケージしか用意されていなかったので、別のパッケージを探しました。

  1. zbarlight 1.2 : Python Package Index
  2. fastzbarlight 0.0.14 : Python Package Index
  3. libzbar-ctypes 0.1.2 : Python Package Index
  4. pyzbar 0.1.4 : Python Package Index
  5. libzbar-cffi 0.2.1 : Python Package Index

fastzbarlightとzbarlightのパッケージはどうやら元のソースコードは同じようです。fastzbarlightはコンパイルオプションを変えて読み取り速度を向上させたらしい(よくわからん)。 で、(fast)zbarlight、libzbar-ctypes、pyzbar、libzbar-cffiのGithubのスターを比べると、1のzbarlightが41でほかよりも多いです。(他のパッケージは0〜10ちょっとくらい)

選ぶ

読み取りに使った画像はこれ。

f:id:uryoya:20170617152721j:plain

ソースコードはこっち。

zbarlight (fastzbarlightはzbarlightのモジュール名を変えただけです。)

from PIL import Image
import zbarlight
import argparse

parser = argparse.ArgumentParser()
parser.add_argument('FILE', help='QR code image file')
args = parser.parse_args()

with open(args.FILE, 'rb') as img_file:
    image = Image.open(img_file)
    image.load()

codes = zbarlight.scan_codes('qrcode', image)
print(f'QR codes: {codes}')

libzbar-ctypes

from PIL import Image
from libzbar import zbar
import argparse

parser = argparse.ArgumentParser()
parser.add_argument('FILE', help='QR code image file')
args = parser.parse_args()

with open(args.FILE, 'rb') as img_file:
    image = Image.open(img_file).convert('L')
    width, height = image.size
    raw = image.tobytes()

image = zbar.Image(width, height, 'Y800', raw)

scanner = zbar.ImageScanner()
scanner.scan(image)

for symbol in image:
    print('decode', symbol.type, 'symbol', symbol.data)

del(image)

pyzbar

from pyzbar.pyzbar import decode
from PIL import Image
import argparse

parser = argparse.ArgumentParser()
parser.add_argument('FILE', help='QR code image file')
args = parser.parse_args()

with open(args.FILE, 'rb') as img:
    codes = decode(Image.open(img))

print(f'QR codes: {codes}')

libzbar-cffiはめんどくさくなってやってないです()

time -pで実行時間を図った結果は次の通り。なお平均とかは取ってないです。

package real user sys
zbarlight 1.59 1.56 0.03
fastzbarlight 1.42 1.37 0.04
libzbar-ctypes 2.25 2.23 0.02
pyzbar 2.29 2.24 0.05

fastzbarlightが一番早く実行が終わり、次いでzbarlight、遅れてlibzbar-ctypes、pyzbarという結果になりました。

libzbar-ctypesはスキャンデータがlibzbar.zbar.Imageオブジェクトになるのでforで取り出す処理が入っています。ただその処理をなくしても速度にあまり変化はありませんでした。

結論としては(fast)zbarlightを使っておけば良さそうです。