こんにちは! けい(Twitter)です。
今回は、Raspberry Pi でQRコードリーダーの作り方についてご紹介していきます。
PythonとOpenCVを組み合わせると簡単に作ることができます。
QRコードの情報を読み取り、webサイトを開く所までをプログラミングしていきたいと思います。
目次
必要な物
Raspberry Pi 本体
今回用いるRaspberry Pi は、ラズパイ4Bです。
ラズパイ3B+で実行するとメモリ不足でエラーになることがあるようです。
原因としては、QRコードの分類器がメモリを沢山使用してしまうためです。
解決策としては、OpenCVの分類器を使用するのではなく別のライブラリを使用することをおすすめします。
Raspberry Piカメラ or Webカメラ
Raspberry Pi のカメラモジュールか、Webカメラを接続することができます。
私はどちらも持っていますが、Webカメラの方が利便性が高いのでWebカメラで動作させたいと思います。
基本的にどんなWebカメラでも動作すると思います。
私は家にあった、logicoolのwebカメラを使用しました。
他にも使用できるカメラなどを以前の記事でまとめているで、ぜひ参考にしてみてください。
環境構築
環境設定
以下の環境で、プログラムを動作させました。
- Raspbian buster 10
- python3.7.3
- opencv:4.1.0
opencvは画像処理用のライブラリですが、opencvのバージョンが4以上のものをインストールする必要があります。
バージョン4以上で、QRコードを認識できる関数が用意されました。
それでは、opencvのインストール手順を見ていきましょう。
opencvをインストール
ラズパイへのopencvのインストールは少々面倒くさい作業です。
OpenCVの依存ライブラリを先にインストールします。
下記コマンドをターミナルで実行してください。
sudo apt install libavutil56 libcairo-gobject2 libgtk-3-0 libqtgui4 libpango-1.0-0 libqtcore4 libavcodec58 libcairo2 libswscale5 libtiff5 libqt4-test libatk1.0-0 libavformat58 libgdk-pixbuf2.0-0 libilmbase23 libjasper1 libopenexr23 libpangocairo-1.0-0 libwebp6
バージョンを指定してopencvをインストールします。
sudo pip3 install opencv-python==4.1.0
これでインストールが完了すると思います。
QRコードを認識するプログラム
ソースコード
まずは、QRコードをwebカメラで取り込んで、QRコードを認識し情報を取り込むプログラムを見ていきましょう。
import cv2
import numpy as np
cap = cv2.VideoCapture(0)
# initialize the cv2 QRCode detector
detector = cv2.QRCodeDetector()
while True:
frame, img = cap.read()
output_img = img.copy()
data, bbox, _ = detector.detectAndDecode(img)
if data:
cv2.putText(output_img, data, (0, 20), cv2.FONT_HERSHEY_SIMPLEX, 1, (255, 0, 0), 5, cv2.LINE_AA)
for i in range(4):
cv2.line(output_img, tuple(bbox[i][0]), tuple(bbox[(i+1)%len(bbox)][0]), (0, 0, 255), 4)
cv2.imshow("QRCODEscanner", output_img)
if cv2.waitKey(1) == ord("q"):
break
cap.release()
cv2.destroyAllWindows()
実行中に、qキーを押すとプログラムが終了します。
実行結果
実際に動作させた様子はYoutubeにアップしました。
コード解説
6行目の「cv2.QRCodeDetector()」の部分で、QRコードを認識するOpencvのクラスを呼び出しています。
11行目の「detector.detectAndDecode(img)」で、元画像imgからQRコードを認識しています。
返り値として3つあり、順に「QRコードからデコードされたデータ」、「QRコードの四角形の頂点の配列」、「整形されたQRコード画像の配列」です。
よって、「data」にはQRコードを読み取った情報、bboxにはQRコードの四隅の座標の配列が格納されています。
14行目で、QRコードの情報を画面に青文字で表示しています。
15,6行目で、QRコードの四隅を結ぶ線を赤色で引いています。
WebサイトをPythonで操作する
先ほどのプログラムは、QRコードの情報を読み取っただけで、実際にQRコードリーダーとしては機能していません。何か足りないですよね。
そう、QRコードを読み取って、Webサイトを開くまでがQRコードリーダーです。
- カメラでQRコードの情報を読み取る
- QRコードの情報を元にWebサイトを開く
先ほどのプログラムで①はできたので、次は②のWebサイトを操作する部分を見ていきましょう。
環境構築②
PythonでWebサイトを操作するためのパッケージとドライバを新たに追加していきます。
- selenium
- Chroniumドライバ
seleniumは、PythonでWebサイトの操作を自動化する際に用いるパッケージです。
Chroniumドライバは、ラズパイにプリインストールされているChroniumをPythonで操作させるために必要なドライバです。
この2つを追加していきましょう。
seleniumのインストール
次のコマンドをターミナルで実行します。
pip3 install selenium
これでインストールは完了したのですが、seleniumパッケージがどこにインストールされたのかが後に必要になってくるので、次のコマンドで場所を確認します。
pip3 show selenium
私の場合は、「/home/pi/.local/lib/python3.7/site-packages/」にインストールされていました。
chroniumドライバのインストール
次のコマンドをターミナルで実行します。
sudo apt-get install chromium-chromedriver
私はこれだけで、自分の使っているChroniumのバージョンと同じバージョンのドライバがインストールされました。
(88.0.4324.187(Official Build)Built on Raspbian , running on Raspbian 10 (32 ビット))
seleniumでChroniumを操作してみる
それでは、最小構成のPythonファイルでseleniumを使って、Chroniumを動作させることができるかを試してみましょう。
import sys
sys.path.insert(0, "/home/pi/.local/lib/python3.7/site-packages/")
from selenium import webdriver
browser = webdriver.Chrome(executable_path="/usr/lib/chromium-browser/chromedriver")
browser.get('https://hellobreak.net')
2行目の「sys.path.insert」は、importできるようにパスに追加しています。
デフォルトのimportできるパスにseleniumがインストールされた場所が登録されていないため、2行目の文を追加してあげないと、importできないので注意です。
ここの部分のパスに先ほど確認した、「 /home/pi/.local/lib/python3.7/site-packages/ 」を記述しています。
このプログラムの実行に成功すると、私のブログのトップ画面が表示されるはずです。
QRコードリーダー
これで、パーツはそろったのでいよいよQRコードリーダーのプログラムを書いていきます。
- カメラでQRコードの情報を読み取る
- QRコードの情報を元にWebサイトを開く
ソースコード
import cv2
import sys
sys.path.insert(0, "/home/pi/.local/lib/python3.7/site-packages/")
from selenium import webdriver
cap = cv2.VideoCapture(0)
detector = cv2.QRCodeDetector()
while True:
frame, img = cap.read()
output_img = img.copy()
data, bbox, _ = detector.detectAndDecode(img)
if data:
cv2.putText(output_img, data, (0, 20), cv2.FONT_HERSHEY_SIMPLEX, 1, (255, 0, 0), 5, cv2.LINE_AA)
for i in range(4):
cv2.line(output_img, tuple(bbox[i][0]), tuple(bbox[(i+1)%len(bbox)][0]), (0, 0, 255), 4)
if cv2.waitKey(1) == ord('a'):
browser = webdriver.Chrome(executable_path="/usr/lib/chromium-browser/chromedriver")
browser.get(data)
break
cv2.imshow("QRCODEscanner", output_img)
if cv2.waitKey(1) == ord('q'):
break
cap.release()
cv2.destroyAllWindows()
QRコードをカメラで読み取っている時にaキーを押すと、そのQRコードのサイトに飛ぶことができます。
実行結果
実際に動作させた様子はYoutubeにアップしました。