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コードがないことを示すメッセージが出力されます。
これらを踏まえて、コード全体をまとめると以下のようになります。
ここから先は
¥ 180
この記事が気に入ったらチップで応援してみませんか?