見出し画像

PythonでPDF内のQRコードを読み取り、ページごとに一覧で出力する方法(GoogleColab)

今回はGoogleColab(Python)で、PDFファイル内に含まれるQRコードを機械的に読み取り、それをページごとに一覧として出力するためのコードを作成していきます。

まず、①単一のPDFからQRコードを作成するための関数を作成し、②その関数をページごとに回していくことで実装していきます。


実装の目標

以下のサンプルPDFでコードを回します。
様々なサイズのQRコード、1ページあたり複数のQRコード、QRコードがないページ等を用意しています。

このサンプルPDFでコードを回した場合、以下のように出力されるようにします。

コードの目標

では、実際に実装に向けて、コードの作成をしていきます。
今回は、話が大掛かりなため、PDFを開いたりするコードの解説は割愛しています。気になる方はコード全体の部分をご覧ください。


①単一のPDFからQRコードを作成するためのコード

extract_qr_from_page関数の定義

def extract_qr_from_page(page):

単一のPDFページに含まれるQRコードを抽出するために定義されています。
pageという引数は、PDF内の特定のページを指します。

QRコードを格納するリストの初期化

qr_codes = []

qr_codesという空のリストを作成し、見つかったQRコードのデータを格納するために使用します。

ページ内の全画像の取得

image_list = page.get_images(full=True)

get_imagesメソッドは、PDFページ内の全画像をリストとして返します。
full=Trueは、画像の完全な情報(位置、サイズなど)を取得するために使用されます。

画像リストの処理

for img in image_list:
    xref = img[0]
    base_image = fitz.Pixmap(doc, xref)

このループは、取得した画像リスト内の各画像に対して処理を行います。
xrefは画像の内部参照(インデックス)を指し、これを使って画像データにアクセスします。
fitz.Pixmap(doc, xref)は、特定の画像のピクセルマップ(画像データ)を取得します。

サブイメージとアルファチャンネルの処理

if base_image.alpha:
    pix = fitz.Pixmap(fitz.csRGB, base_image)
else:
    pix = base_image

画像がサブイメージ(他の画像の一部)かどうか、またアルファチャンネル(透明度情報)を持っているかどうかを確認しています。
アルファチャンネルが存在する場合、画像をRGBフォーマット(赤、緑、青の色情報のみ)に変換しています。これは透明度情報を排除するために必要です。

PPM形式への変換

img_bytes = pix.tobytes("ppm")

画像データ(pix)をPPM(Portable Pixmap Format)形式に変換し、バイト配列として保存します。
PPMはシンプルな画像フォーマットで、多くの画像処理ライブラリで扱いやすい形式です。

PILを使ってイメージを開く

image = Image.open(io.BytesIO(img_bytes))

PythonのPIL(Python Imaging Library)を使用して、バイトデータから画像を生成しています。
io.BytesIOは、バイトデータをファイルライクなオブジェクトに変換し、Image.openによって読み込まれます。

QRコードのデコード

decoded_objects = decode(image)

decode関数(pyzbarライブラリからインポート)は、画像内のQRコードを探し、それらをデコードします。
この関数はデコードされたQRコードの内容を含むオブジェクトのリストを返します。

デコードされたQRコードのデータの抽出

for obj in decoded_objects:
qr_codes.append(obj.data.decode("utf-8"))

デコードされた各QRコードオブジェクトからデータ(通常はバイト列)を取り出し、文字列に変換してリストに追加します。

メモリ管理

pix = None

画像処理が完了した後、ピクセルマップオブジェクトをNoneに設定して、メモリを解放します。

抽出されたQRコードのリストを返す

return qr_codes

最後に、見つかったすべてのQRコードのデータを含むリストqr_codesを返します。


②関数をページごとに回していく(反復処理)

各ページを反復処理する

for page_num in range(len(doc)):

forループを使用して、PDFドキュメント内の全ページを順番に処理しています。
range(len(doc))は、ドキュメントのページ数に等しい範囲の数値シーケンスを生成します。これにより、各ページに対してループが実行されます。

ページを読み込む

page = doc.load_page(page_num)

doc.load_page(page_num)は、ループ内の現在のページ番号(page_num)に対応するPDFページを読み込みます。
page変数には、処理するページのデータが格納されます。

QRコードを抽出

qr_codes = extract_qr_from_page(page)

extract_qr_from_page関数を呼び出し、先ほど読み込んだページからQRコードを抽出します。
この関数は、該当ページにQRコードが見つかった場合、それらの内容を含むリストを返します。

QRコードの存在チェックと出力

if qr_codes: print(f"ページ {page_num + 1} のQRコード: {qr_codes}") else: print(f"ページ {page_num + 1} にQRコードは見つかりませんでした")

if qr_codes:は、qr_codesリストに何かが含まれているかどうかをチェックします。これは、現在のページにQRコードが見つかったかどうかを判定するために使用されます。
qr_codesにQRコードのデータがある場合、そのページ番号と共にQRコードの内容を出力します。
QRコードが見つからない場合は、そのページにQRコードがないことを示すメッセージが出力されます。


これらを踏まえて、コード全体をまとめると以下のようになります。

ここから先は

1,707字

¥ 180

この記事が気に入ったらサポートをしてみませんか?