PDF データを PNG 画像に変換する方法

書籍の内容をデジタル化するべくスキャナーでスキャンしたのですが、まさかの文字化けでスキャンができなかったため、 OCR でテキストを抽出することになりました。
しかし、 PDF で保存していたためそのままでは読み込めず、一旦 PNG 画像に変換する必要がでてきました。

今回はその備忘録です。

# 環境
今回の環境は下記のとおりです。

## 開発端末
- OS：Windows 11 Pro
- CPU：Intel Core i7-9750H
- メモリ：64GB
- GPU：NVIDIA GeForce RTX 2070 Max-Q

## Python 環境
- Python：3.8.10
- 仮想環境：Poetry

:::note info
Poetry について
Poetry の詳細は、下記の記事を参考にしてください。
https://qiita.com/IoriGunji/items/290db948c11fdc81046a
:::

# ライブラリ類のインストール
必要なライブラリ類をインストールしていきます。

## pdf2image のインストール
pdf2image ライブラリをインストールします。

### pip の場合
```shell
pip install pdf2image
```

### Poetry の場合
```shell
poetry add pdf2image
```

## Poppler のインストール
pdf2image は pdftoppm と pdftocairo をラップして PDF を PIL Image オブジェクトに変換しているため、別途 Poppler をインストールする必要があります。

下記から `Release-xx.xx.x-x.zip` の ZIP ファイルをダウンロードして解凍します。

https://github.com/oschwartz10612/poppler-windows/releases/

![poppler_download.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/212972/40b2876d-7a41-c218-10ec-aec75595ac4c.png)

> **補足**  
> 今回は `Release-23.08.0-0.zip` を利用しました。

解凍した `poppler-xx.xx.x` フォルダは `poppler` にリネームして、 Python コードを同じディレクトリに移動します。 

# Python コードの作成
PDF ファイルを PNG 画像に変換するために Python コードを作成します。

```main.py
import os
import glob
from pathlib import Path
from pdf2image import convert_from_path

# 定数定義
POPPLER_DIR = "poppler/Library/bin"
PDF_DIR = "pdf"
IMAGES_DIR = "images"

# PDF を PNG 画像に変換
def main():
    pdfs_path = get_pdfs_path(PDF_DIR)
    for pdf_path in pdfs_path:
        print('変換中ファイル：' + os.path.basename(pdf_path))
        pdf_image = pdf_to_imageobject(pdf_path, POPPLER_DIR)
        output_dir = os.path.join(IMAGES_DIR, os.path.splitext(os.path.basename(pdf_path))[0])
        pillowimage_to_imagefile(pdf_image, output_dir)

# PDF ファイルのパスを一括取得
def get_pdfs_path(input_dir):
    pdf_path = os.path.join(Path(__file__).parent, input_dir)
    pdfs_path = glob.glob(os.path.join(pdf_path, '*.pdf'))
    return pdfs_path

# PDF を Pillow Image オブジェクトに変換
def pdf_to_imageobject(pdf_path, poppler_dir, dpi = 300):
    poppler_path = os.path.join(Path(__file__).parent, poppler_dir)
    images = convert_from_path(pdf_path=pdf_path, poppler_path=poppler_path, dpi=dpi)
    return images

# Pillow Image オブジェクトを画像ファイルに変換し保存
def pillowimage_to_imagefile(images, output_dir):
    image_dir = os.path.join(Path(__file__).parent, output_dir)
    os.makedirs(image_dir, exist_ok=True)
    for i, image in enumerate(images):
        image_name = str(i + 1) + ".png"
        image_path = os.path.join(image_dir, image_name)
        image.save(image_path, "PNG")

if __name__ == "__main__":
    main()
```

# ディレクトリ構造の確認
ディレクトリ構造が下記の様になっているか確認してください。

root
 ├ images
 ├ pdf
 │  ├ sample1.pdf
 │  └ sample2.pdf
 ├ poppler
 │  ├ Library
 │  │  ├ bin
 │  │  ├ include
 │  │  ├ lib
 │  │  └ share
 │  └ share
 └ main.py

# PDF ファイルを PNG 画像に変換
`pdf` ディレクトリに変換したい PDF ファイルを保存し、 `main.py` を実行します。
変換された画像が `images` ディレクトリに保存されていれば完了です。

# 参考文献
下記のサイトを参考にさせて頂きました。

https://gammasoft.jp/blog/convert-pdf-to-image-by-python/

https://pypi.org/project/pdf2image/

https://laboratory.kazuuu.net/convert-a-pdf-file-to-an-image-using-pdf2image-in-python/

https://pdf2image.readthedocs.io/en/latest/_modules/pdf2image/pdf2image.html?highlight=convert_from_path

<!-- EOF -->