Python, Pillow, qrcodeでQRコード画像を生成、保存

Posted: | Tags: Python, Pillow, 画像処理

PythonのQRコード生成ライブラリqrcodeを使うと、簡単にQRコード画像を生成できる。Pillowのメソッドを使って、他の画像の中にQRコードを埋め込んだり、逆にQRコードに画像を埋め込んだりすることも可能。

以下の内容について説明する。

  • PythonのQRコード画像生成ライブラリ「qrcode」
  • コマンドラインでQRコード画像作成
  • PythonのコードでQRコード画像作成
    • 生成されるQRコードのバージョン(引数version
    • 誤り訂正レベル(引数error_correction
    • セルのサイズ(引数box_size
    • 余白の幅(引数border
    • 色(引数fill_color, back_color
  • QRコードを画像に埋め込む
  • QRコードの中に画像を埋め込む

QRコードの検出については以下の記事を参照。厳密には検証していないが、検出精度はZBar(pyzbar)のほうが良さそう。

※QRコードは株式会社デンソーウェーブの登録商標です。

PythonのQRコード画像生成ライブラリ「qrcode」

QRコードは、ISO(ISO/IEC18004)、JIS(JIS-X-0510)で規格化されている、四角い黒白の点(セル)で構成される二次元コード。

PythonにはQRコード画像生成のためのライブラリ「qrcode」がある。

pip(環境によってはpip3)でインストールできる。

$ pip install qrcode

Pillow(PIL)を使うのであわせてインストールしておく。

$ pip install pillow

コマンドラインでQRコード画像作成

シンプルなQRコード画像を作成するだけならコマンドラインでOK。

qrcodeをインストールするとqrコマンドが使えるようになる。

$ qr "text for qrcode" > qrcode.png

この例の場合、text for qrcodeという文字列データを含んだqrcode.pngという名前のQRコード画像ファイルが生成される。文字列の長さに応じて画像サイズが自動で調整される。

QRコードが保持しているのはあくまでも文字列であって、その文字列をどのように処理するかは読み取り側のアプリケーションに依存する。

例えば、スマホのカメラアプリ(QRコード読み取りに対応したもの)では、文字列中にURLが含まれているとそのURLを開くかどうかの通知を表示し、ユーザーが許可すれば規定のブラウザで開くようになっているものが多い。単純にWebサイトに飛ばしたい場合は、URLの文字列をQRコード化すればよい。

PythonのコードでQRコード画像作成

qrcode.make()PilImage型のオブジェクトが生成される。

size属性で画像のサイズを取得するなど、Pillow(PIL)のImage型の属性やメソッドなどがそのまま使える。

画像ファイルとして保存するにはsave()

import qrcode

img = qrcode.make('test text')

print(type(img))
print(img.size)
# <class 'qrcode.image.pil.PilImage'>
# (290, 290)

img.save('data/dst/qrcode_test.png')

python qrcode

QRCodeクラスを使って、細かい設定を変更することもできる。

基本の流れは以下の通り。

qr = qrcode.QRCode()
qr.add_data('test text')
qr.make()
img = qr.make_image()
img.save('data/dst/qrcode_test2.png')

もろもろの設定をすると以下のようになる。

qr = qrcode.QRCode(
    version=12,
    error_correction=qrcode.constants.ERROR_CORRECT_H,
    box_size=2,
    border=8
)
qr.add_data('test text')
qr.make()
img = qr.make_image(fill_color="red", back_color="#23dda0")
img.save('data/dst/qrcode_test2_2.png')

python qrcode advance

以下、それぞれの引数について説明する。

生成されるQRコードのバージョン(引数version)

コンストラクタQRCode()の引数versionで、生成されるQRコードのバージョンを設定できる。

QRコードの情報量とバージョンの関係についてはデンソーウェーブ公式の以下のページを参照。

バージョンの値が大きくなるとQRコードに含まれるセル(黒白の四角)の数が多くなり、画像サイズと情報量が増える。version=1が最小でversion=40が最大。

引数versionを与えることで、最適なバージョン(最小限のサイズ)よりも大きいQRコード画像を生成できる。データ内容が異なる複数のQRコードを同じ大きさで作成したいときに便利。

なお、小さいバージョンを指定しても、データが収まらない場合は自動的にデータが収まる最小限のバージョンになる。

誤り訂正レベル(引数error_correction)

QRCode()の引数error_correctionで誤り訂正レベルを設定できる。

以下の4種類がある。カッコ内は誤り訂正能力(全コードワードに対する誤り訂正率)。

  • qrcode.constants.ERROR_CORRECT_L(約7%)
  • qrcode.constants.ERROR_CORRECT_M(約15%, デフォルト)
  • qrcode.constants.ERROR_CORRECT_Q(約25%)
  • qrcode.constants.ERROR_CORRECT_H(約30%)

QRコードの誤り訂正機能についてはデンソーウェーブ公式の以下のページを参照。

同じ長さの文字列をQRコード化する場合、誤り訂正レベルを高くすると生成されるQRコード画像サイズが大きくなる。

セルのサイズ(引数box_size)

QRCode()の引数box_sizeでセル(四角い黒白の点)のサイズ(ピクセル)を設定できる。

versionが同じ(セルの数が同じ)でも、box_sizeを変更することで生成される画像のサイズを変更できる。

デフォルトは10

余白の幅(引数border)

QRCode()の引数borderで外周の余白の幅(セルの数)を設定できる。box_size * borderが余白の幅のピクセルとなる。

デフォルトは4で、仕様上の最小幅になっている。

色(引数fill_color, back_color)

make_image()メソッドの引数fill_color, back_colorで色を設定できる。QRCode()の引数ではないので注意。

black, white, redなどの名前や#xxxxxxのスタイルで指定する。

QRコードを画像に埋め込む

PilImage型のオブジェクトは、PillowのImageオブジェクトのpaste()メソッドでそのまま他の画像に貼り付けられる。

右下隅にQRコードを貼り付ける例。

import qrcode
from PIL import Image

img_bg = Image.open('data/src/lena.jpg')

qr = qrcode.QRCode(box_size=2)
qr.add_data('I am Lena')
qr.make()
img_qr = qr.make_image()

pos = (img_bg.size[0] - img_qr.size[0], img_bg.size[1] - img_qr.size[1])

img_bg.paste(img_qr, pos)
img_bg.save('data/dst/qr_lena.png')

python qrcode pillow image

paste()メソッドについての詳細は以下の記事を参照。

QRコードの中に画像を埋め込む

QRコードの中に画像を埋め込むのも簡単。

なお、QRコードにイラストなどの画像を重ねると規格から外れるため、公式には非推奨とされている。

色を付けたりイラストを入れるような使い方をしても問題ありませんか?

QRコードにイラストを重ねたり、デザインをのせて変形してしまうと、ちょっとした汚れや欠けでも読み取り出来なくなったり、読み取りの反応が悪くなってしまうことがありますので推奨しておりません。安定した読み取りという面から、JIS、ISOの規格で制定されている内容に従ってご利用いただくことを推奨しております。
また、QRコードにイラストを重ねたりデザインを乗せるということは、QRコードの規格から外れ「QRコードではないもの」となってしまう可能性がございます。デンソーウェーブは、JIS、ISOの規格に沿ったQRコードに限っては特許権を行使しませんが、規格を逸脱したQRコードについてはこの限りではございませんので、特許権を行使させていただくこともございます。

face = Image.open('data/src/lena.jpg').crop((175, 90, 235, 150))

qr_big = qrcode.QRCode(
    error_correction=qrcode.constants.ERROR_CORRECT_H
)
qr_big.add_data('I am Lena')
qr_big.make()
img_qr_big = qr_big.make_image().convert('RGB')

pos = ((img_qr_big.size[0] - face.size[0]) // 2, (img_qr_big.size[1] - face.size[1]) // 2)

img_qr_big.paste(face, pos)
img_qr_big.save('data/dst/qr_lena2.png')

python qrcode pillow image2

埋め込む画像のサイズにもよるが、誤り訂正レベル(引数error_correction)を高めに設定しておいたほうが無難。また、白黒のQRコードにカラー画像を埋め込む場合は、QRコード画像をconvert('RGB')RGBモードに変換する必要がある。

関連カテゴリー

関連記事