19
22

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

Pythonによる文字表示付きQRコードの大量生成

Last updated at Posted at 2020-12-25

記事の概要

Pythonのqrcodeを用いてQRコードを自動生成します。
QRコードに識別番号も同時に記載したいので、pillowやその他のツールも用いて文字も挿入します。

(追記)
@konikoni428 さんのご指摘により、画像をグレースケールに変換することで、文字が荒くなるのを回避できることが分かり、「画像の拡大・縮小処理」が不要になりました。(追記終わり)

(追記)
日本語の文字を表示させるためには、fontを日本語に対応したもの変更しないといけないようです。
詳細は以下の記事をご参照ください。

(追記終わり)

ツールのインストール

QRコードの生成にはqrcodeを使用します。

qrcodeをインストールしてください。

pip install qrcode

画像の加工にはpillowをします。

pillowをインストールしてください。

pip install Pillow

QRコードの生成

import qrcode
from PIL import Image

img = qrcode.make("Hello World!")
img.save('test.png')

img.show()
test.png

生成されたQRコードが正しく読み取れるかは、http://qrcode.red/ で読み込んで確認できます。

qrコード読み取り結果.png

QRコードの生成(詳細設定)

詳細な設定を行うこともできます。

import qrcode
from PIL import Image

qr = qrcode.QRCode(
    version=3,
    error_correction=qrcode.constants.ERROR_CORRECT_L,
    box_size=10,
    border=2,
)
qr.add_data('Hello World!')
qr.make(fit=True)

img = qr.make_image(fill_color="black", back_color="white").convert('L')
img.save('test.png')

img.show()
  • version
    • セル数を決めるパラメータで、1から40の値に設定できます。
    • 1で21セルx21セル、2で25セルx25セル、40で177セルx177セルです
    • 以下参照
  • error_correction
    • 誤り訂正レベルで以下のパラメータから選択します
      • ERROR_CORRECT_L
        • 7%以下のエラーを修正
      • ERROR_CORRECT_M
        • 初期設定値
        • 15%以下のエラーを修正
      • ERROR_CORRECT_Q
        • 20%以下のエラーを修正
      • ERROR_CORRECT_H
        • 30%以下のエラーを修正
  • box_size
    • ボックスのピクセル数
  • border
    • 境界線の太さ
    • 初期値4(最小設定値)

(追記)
@konikoni428 さんのご指摘を受けて、QRコードをグレースケールに変換しています。

img = qr.make_image(fill_color="black", back_color="white").convert('L')

もしデータサイズをなるべく小さくしたいなどの理由で白黒2階調にしたい場合は、グレースケール変換を省略ください

img = qr.make_image(fill_color="black", back_color="white")

(追記終わり)

余白の追加

画像に余白を追加、削除するにはnote.nkmk.meにて公開されている関数add_marginが便利です。

Python, Pillowで画像の上下左右に余白を追加しサイズ変更

関数の詳細は上記ブログを参照してください。
今回はQRコードの下に文字を表示する余白を作りたいので、下方向にサイズを追加します。
背景色は白(#ffffff)にしています。

from PIL import Image
img = Image.open('test.png') #先ほどに保存した画像を読み込む
img_new = add_margin(img, 0, 0, 100, 0, '#ffffff')

img_new.show()

この関数はマイナスの数値を入力すれば、サイズを縮小できるので、画像サイズの調整に便利です。

画像サイズの変更

後で使用するので、画像サイズの拡大縮小方法を紹介します。
resizeにより画像を拡大縮小できます。

from PIL import Image, ImageDraw, ImageFont
img = Image.open('test.png') #画像の読み込み
img_resize = img.resize((int(img .width / 2), int(img .height / 2)), Image.LANCZOS)

img_resize.show()

'Image.LANCZOS' は圧縮フィルタを指定するパラメータです。
以下から選択します。一般的に下の方が圧縮率が低くなる代わりに、画像はキレイになります。
このパラメータは省略可能で、省略すると自動的にNEARESTが適用されます。

  • NEAREST
    • 何も指定しなければ、これが選択される
  • BOX
  • BILINEAR
  • HAMMING
  • BICUBIC
  • LANCZOS

文字の挿入

Pythonで一気に画像編集できるPillowを使った画像処理のチートシートにて紹介されていた方法で、文字を挿入してみました。

from PIL import Image, ImageDraw, ImageFont
img = Image.open('test.png')
img_new = add_margin(img, 0, 0, 100, 0, '#ffffff')

draw = ImageDraw.Draw(img_new) 
font = ImageFont.truetype("./fonts/arial.ttf", 55) 
draw.text((20, 320), 'Hello! 12345', font=font, fill='#000000') 
img_new.save('test.png')

img_new.show()
test.png

フォントの種類は変更できます。
以下を参照して選択ください。
https://helpx.adobe.com/jp/x-productkb/global/cq08041028.html

文字の画像解像度が荒い場合

(追記)
画像をグレースケールに変換している場合は、文字画像は荒くなりません。
以下は参考用に残しますが、必要のない処理になります。
(追記終わり)

小さなサイズのQRコードに対しては、上記の方法で挿入した文字は荒いという欠点があります。
そこでresizeで拡大した解像度の高い画像を保存し、それを画像サイズを縮小するツールで適切なサイズにします。

まずは余白を入れた画像を10倍に拡大し、そこに大きめの文字を挿入します。

from PIL import Image, ImageDraw, ImageFont
img = Image.open('test.png')
img_add = add_margin(img, 0, 0, 100, 0, '#ffffff')

img_resized = img_add.resize((int(img_add.width*10), int(img_add.height*10)), resample=Image.LANCZOS)

draw = ImageDraw.Draw(img_resized)
font = ImageFont.truetype("./fonts/arial.ttf", 530) 
draw.text((190, 3200), 'Hello! 12345', font=font, fill='#000000') 
img_resized.save('test.png')

img_resized.show()

画像の縮小には、フリーソフトの 藤 -Resizer- を使用しました。
何百枚の画像でも、アイコンにドラッグ&ドロップすれば一括で縮小してくれます。

画像縮小.png

文字がキレイに表示されています。

test_s.png

画像編集ソフトで確認すると、印刷しても問題ない解像度であることが分かります。

qrコード画像解像度結果.png

大量生成

今までのコードを関数化すれば、連番のQRコードを大量生成できます。

フォルダの自動作成は以下の記事をマネしました。
Python フォルダの作成 既存かチェックあり

import os
import qrcode
from PIL import Image, ImageDraw, ImageFont

def add_margin(pil_img, top, right, bottom, left, color):
    #先ほどに紹介した記事のコードをコピペしてください。
    return result

def qr_generator(number):
    qr = qrcode.QRCode(
        version=2,
        error_correction=qrcode.constants.ERROR_CORRECT_L,
        box_size=9,
        border=4,
    )
    qr.add_data('Hello!' + number)
    qr.make(fit=True)

    img = qr.make_image(fill_color="black", back_color="white").convert('L')
    img_add = add_margin(img, -15, -15, 45, -15, '#ffffff')
    # (追記)画像拡大・縮小工程が必要だった時の設定
    # img_resized = img_add.resize((int(img_add.width*10), int(img_add.height*10)), resample=Image.LANCZOS)
    
    draw = ImageDraw.Draw(img_add)
    font = ImageFont.truetype("./fonts/arialbd", 45)
    num = number

    # (追記)画像拡大・縮小工程が必要だった時の設定
    #draw.text((200, 2550), 'Hello!' + num, font=font, fill='#000000') 
    #img_resized.save('./my_qr_code/' + number + '.png', quality=95)

    draw.text((15, 250), 'Hello! ' + num, font=font, fill='#000000') 
    img_add.save('./my_qr_code/' + number + '.png', quality=95)

    #img_add.show()


def main(total_num):
    new_path = "my_qr_code"#フォルダ名
    if not os.path.exists(new_path):#ディレクトリ有無確認
        os.mkdir(new_path)
    
    for number in range(total_num):
        qr_generator(str(1000+number))    
    
main(100) 

以上で作成した画像を藤 -Resizer- で一括縮小すれば完成です。
(追記:画像拡大・縮小が不要になったので、必要のない処理になりました)

19
22
2

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
19
22

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?