Raspberry PiでQRコードを読み取ってみる

# はじめに
QRコードをカメラで読み取り、QRコードを認識させて見ようと試してみました。
カメラの映像を表示させたいためにTkinter（GUI）を使用して表示させるようにしました。

# 利用するデバイス
- Raspberry Pi 3 (2018-11-13-raspbian-stretch をインストール）
- USB接続のWebカメラ　[BUFFALO BSWHD06M](https://www.buffalo.jp/product/detail/bswhd06mbk.html)

# 使用したライブラリ
- opencv-python 4.1.1.26 
- pillow 4.0.0
- pyzbar 0.1.8
- Tkinter 3.5.3-1

Python 3.5.3 を使用。

```
sudo pip3 install opencv-python
sudo pip3 install pillow
sudo pip3 install pyzbar
sudo apt-get install python3-tk
```

# こんな感じでQRコードを読み取れますよ。

<blockquote class="twitter-tweet"><p lang="ja" dir="ltr">Raspberry Pi でQRコードリーダーを作ってみた。<br>描画がカクカクしているけど、読み取りの反応早いｗ<a href="https://twitter.com/hashtag/RaspberryPi?src=hash&amp;ref_src=twsrc%5Etfw">#RaspberryPi</a> <a href="https://twitter.com/hashtag/Raspberrypi3?src=hash&amp;ref_src=twsrc%5Etfw">#Raspberrypi3</a> <a href="https://t.co/TT9fWMDaC9">pic.twitter.com/TT9fWMDaC9</a></p>&mdash; t_kobanyn (@kobanyn) <a href="https://twitter.com/kobanyn/status/1201882713860517891?ref_src=twsrc%5Etfw">December 3, 2019</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>

# カメラ接続＆認識されたか確認
カメラをラズパイに接続して、lsusbコマンドで認識されたか確認します。

```
$ lsusb
Bus 001 Device 005: ID 413c:2107 Dell Computer Corp. 
Bus 001 Device 004: ID 046d:c52f Logitech, Inc. Unifying Receiver
Bus 001 Device 006: ID 0411:0260 BUFFALO INC. (formerly MelCo., Inc.) 
Bus 001 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub
```

# 実行してみる
## GUIを起動させるため、 Raspberry上のターミナルで実行します
```
python3 qrcode_reader.py
```

# ソースはこちら
```python:qrcode_reader.py
#!/usr/bin/env python
# -*- coding: utf8 -*-
from time import sleep
import tkinter

import cv2
from PIL import Image, ImageTk
from pyzbar import pyzbar

root = tkinter.Tk()
root.title('QR reader')
root.geometry('640x488')

CANVAS_X = 640
CANVAS_Y = 480

canvas = tkinter.Canvas(root, width=CANVAS_X, height=CANVAS_Y)
canvas.pack()

cap = cv2.VideoCapture(0)

def capture_code():
	global CANVAS_X, CANVAS_Y

	ret, frame = cap.read()
	if ret == False:
		print("Not Image")
	else:
		image_rgb = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)
		image_pil = Image.fromarray(image_rgb)
		image_tk = ImageTk.PhotoImage(image_pil)
		canvas.image_tk = image_tk
		canvas.create_image(CANVAS_X / 2, CANVAS_Y / 2, image=image_tk)

		decoded_objs = pyzbar.decode(frame)

		if decoded_objs != []:
			for obj in decoded_objs:
				print('Type: ', obj)
			
				str_dec_obj = obj.data.decode('utf-8', 'ignore')
				print('QR coed: {}'.format(str_dec_obj))
				left, top, width, height = obj.rect
				
				canvas.create_rectangle(left, top, left + width, top + height, outline='green', width=5)
				canvas.create_text(left + (width / 2), top - 30, text=str_dec_obj, font=('Helvetica', 20, 'bold'), fill='firebrick1')
		
		
	canvas.after(10, capture_code)
capture_code()
root.mainloop()
```

### 取得したデータはこんな感じです
#### QRコード情報
```
Type:  Decoded(data=b'https://jsl.co.jp', type='QRCODE', rect=Rect(left=133, top=43, width=110, height=113), polygon=[Point(x=133, y=43), Point(x=136, y=153), Point(x=242, y=156), Point(x=243, y=46)])
Type:  Decoded(data=b'https://geeklab-nagano.com', type='QRCODE', rect=Rect(left=135, top=242, width=107, height=102), polygon=[Point(x=135, y=242), Point(x=139, y=341), Point(x=241, y=344), Point(x=242, y=246)])
```
#### バーコード情報もとれる
```
Type:  Decoded(data=b'4902201428811', type='EAN13', rect=Rect(left=237, top=123, width=116, height=58), polygon=[Point(x=237, y=123), Point(x=237, y=181), Point(x=353, y=176), Point(x=353, y=136), Point(x=346, y=131)])
QR coed: 4902201428811
```