Photoruction工事中!

Photoructionの開発ブログです!

PyMuPDFでPDFを操作する⓶

こんにちは!株式会社Photoructionでエンジニアとしてインターンをしている渡邉圭太郎です。 Photoruction Advent Calendar 202220日目の記事です。

はじめに

自分たちのチームでは、PDFを扱って画像解析を行うことが多いです。以前まではpdfminerを使用していましたが、日本語ドキュメントの豊富さなどから現在はPyMuPDFというライブラリを使用しています。本記事はPyMuPDFを使ったPDFのベクターファイルの取得方法を紹介します。

PDFのベクターファイルとは

PDFのファイル形式には大きわけてラスターファイルとベクターファイルの二つが存在します。それぞれの特徴としては以下の通りです。

ラスターファイル

ラスターファイルとは、色のついた小さい正方形であるピクセル(画素)を大量に組み合わせた画像で、写真などの高精細な画像を形成できます。ピクセル(画素)数が多いほど高画質になり、少ないほど低画質になります。画像のピクセル数は、ファイル形式によって異なります。(https://www.adobe.com/jp/creativecloud/file-types/image/comparison/raster-vs-vector.htmlから引用)

ベクターファイル

ベクターファイルは、数式、直線、曲線を使用して、グリッド上の固定点により画像を表示します。ベクターファイルにはピクセルはありません。ベクターファイルは、数式によってシェイプ、境界線、塗りの色を表現し、画像を構築します。 ベクター画像はサイズが変わっても数式により再計算できるため、品質に影響を及ぼすことなく拡大縮小できます。(https://www.adobe.com/jp/creativecloud/file-types/image/comparison/raster-vs-vector.htmlから引用)

要するにベクターファイルは矩形や文字情報が画像としてではなく格納されています。これはPyMuPDFを使用すると簡単に取得できるのです。

PDFの読み込み

PyMuPDFの読み込みについては、11日目の酒井さんの記事をぜひ参考にしてください!

図形の取得

# PDFファイルパスの読み込み
pdf_path = input()

# 1ページ目の要素を取得
document = fitz.open(pdf_path)
page = document[0]

# 図形の取得
paths = page.get_cdrawings()
line_list, rect_list, quad_list, curve_list = [], [], [], []
for path in paths:
    items = path['items']
      for item in items:
          if item[0] == 'l':
              line_list.append([item[1], item[2]])
              # pdfにlineを追加する場合
              # page.draw_line(line[0], line[1], color=(1, 0, 0))
          elif item[0] == 're':
              rect_list.append(item[1])
          elif item[0] == 'qu':
              quad_list.append(item[1])
                    elif item[0] == 'c':
                            curve_list.append(item[1])

テキストの取得

# PDFファイルパスの読み込み
pdf_path = input()

# 1ページ目の要素を取得
document = fitz.open(pdf_path)
page = document[0]

# テキストの取得
words = page.get_text_words()

text_info = []
coordinates_list = []
for w in words:
    x1, y1, x2, y2 = w[:4]
    x1, y1 = fitz.Point(x1, y1) * page.rotation_matrix
    x2, y2 = fitz.Point(x2, y2) * page.rotation_matrix
    x1, y1, x2, y2 = min(x1, x2), min(y1, y2), max(x1, x2), max(y1, y2)
    if x1 == x2:
        x1 -= 0.1
        x2 += 0.1
    if y1 == y2:
        y1 -= 0.1
        y2 += 0.1
  
    text_info.append({'text': w[4], 'coordinates': [x1, y1, x2, y2]})

おわりに

PyMuPDFでは他にもPDFを編集したりする操作も可能となっています。もし気になる方はチェックしてみてください!

株式会社フォトラクションでは一緒に働く仲間を募集しています