PDFファイルの座標位置を正確に取得する方法:実践的テクニックとツール紹介

座標取得の基礎知識

PDFは「ページ」単位で設計されたマークアップ言語で、文字、図形、画像などを座標で配置します。
しかし、実際に座標を取得する場合は「ページ上の座標」か「ページ内の物体の座標」かで分かれます。
ここでは両方の取得方法を網羅し、最も使い勝手の良いツールと実装例をご紹介します。


1. PDFの座標体系とは何か?

タイプ 座標系 原点 単位 備考
ページ座標 カラーモード 左下 1 / 1dpi(ポイント) PDF 仕様では 1ポイント = 1/72インチ
ページオブジェクト座標 物体単位 物体の左下 同上 画像、図形の bbox で取得
絶対座標 複数ページ 上部左 同上 PDF 内のページを合わせた座標
出力座標 物理出力(印刷) 上部左 物理単位 プリンタ解像度に依存

原点の違いに注意

  • ページ座標は左下が原点(0,0)。
  • 印刷座標は上部左が原点。
  • Webブラウザの PDF.js のように CSS の基準に合わせる場合、上部左が原点になることもある。

2. 何のために座標を取得したい?

目的 典型的な用途 主要ツール
テキスト抽出 指定箇所のテキストを拾う pdfminer.six, PyMuPDF
図形・画像の位置取得 位置合わせやリンク設置 PyMuPDF, pdfplumber
レイアウト解析 レイアウトを理解し、再生成 Camelot, Tabula
PDFのビジュアル化 文字・図形の座標をマッピング PDFBox, iText, PDF.js
自動マークアップ 文字にハイライトやリンク付与 Poppler, Ghostscript

3. 言語別:Pythonでの実装パターン

Python は PDF 処理ライブラリが豊富で、スクリプトを書きやすいのが特徴です。

3-1. pdfminer.six の利用

from pdfminer.high_level import extract_pages
from pdfminer.layout import LTTextBoxHorizontal, LTTextLineHorizontal

for page_layout in extract_pages("sample.pdf", page_numbers=[0]):
    for element in page_layout:
        if isinstance(element, LTTextBoxHorizontal):
            for text_line in element:
                if isinstance(text_line, LTTextLineHorizontal):
                    bbox = text_line.bbox  # (x0, y0, x1, y1)
                    print(f"Text: {text_line.get_text().strip()}, BBox: {bbox}")

メリット

  • 細かなレイアウト情報まで取得できる
  • 文字単位での座標が取得できる

デメリット

  • 速度が遅い
  • 画像や図形は扱いにくい

3-2. PyMuPDF (fitz) の利用

import fitz

doc = fitz.open("sample.pdf")
page = doc[0]

# 文字情報を取得
texts = page.get_text("dict")
for block in texts["blocks"]:
    for line in block["lines"]:
        for span in line["spans"]:
            # span["bbox"] => (x0, y0, x1, y1)
            print(f"Text: {span['text']}, BBox: {span['bbox']}")

# 画像情報を取得
for img in page.get_images():
    xref = img[0]
    pix = fitz.Pixmap(doc, xref)
    print(f"Image at {pix.rect}")

メリット

  • 画像・図形の座標も簡単に取得
  • PNG / JPEG への変換も容易
  • 速度が速い

デメリット

  • テキスト情報は文字列単位で取得しやすい
  • カスタムレイアウトはやや難しい

3-3. pdfplumber の利用(表や位置情報が必要な時)

import pdfplumber

with pdfplumber.open("sample.pdf") as pdf:
    page = pdf.pages[0]
    # ページ全体の座標情報を取得
    for obj in page.objects:
        if obj["type"] == "text":
            print(obj["x0"], obj["top"], obj["x1"], obj["bottom"])
  • 表抽出に特化した extract_tables も利用可能
  • 文字オブジェクトの座標情報が type で判別できる

4. C# で PDF の座標を取得する

4-1. PDFBox (Java) を使用する例

using (PDDocument doc = PDDocument.load(new File("sample.pdf"))) {
    PDPage page = doc.getPage(0);
    PDResources res = page.getResources();
    var contents = page.getContents();
}

※ 物体単位で座標を取得するには PDFTextStripper を継承して writeString 内で TextPosition を取得します。

4-2. iTextSharp (C# 版) を使う手順

PdfReader reader = new PdfReader("sample.pdf");
PdfDictionary pageDict = reader.GetPageN(1);
PdfArray mediaBox = pageDict.GetAsArray(PdfName.MEDIABOX);
  • PdfContentStreamProcessor を使えば、図形・文字ごとの位置情報が取得可能です。

5. JavaScript で直接ブラウザ上から座標を取得

PDF.js を使用すると、PDF を Canvas として描画しながら座標情報を取得できます。

pdfjsLib.getDocument('sample.pdf').promise.then((pdf) => {
  pdf.getPage(1).then((page) => {
    const viewport = page.getViewport({ scale: 1.0 });
    const canvas = document.createElement('canvas');
    const ctx = canvas.getContext('2d');
    canvas.height = viewport.height;
    canvas.width = viewport.width;
    const renderContext = {
      canvasContext: ctx,
      viewport: viewport
    };
    page.render(renderContext).promise.then(() => {
      const textContent = page.getTextContent();
      textContent.items.forEach((item) => {
        console.log(item.str, item.transform);
      });
    });
  });
});
  • item.transform[a, b, c, d, e, f] の行列で、座標変換が含まれます。
  • 座標系を「左下原点から「上下反転」→左上原点」へ変換すると、ページ描画時の座標と同一になります。

6. PDF の座標操作を便利にするツール群

ツール 概要 特長
Poppler デフォルトの PDF 測定ツール。pdfinfo, pdftotext, pdfimages など。 ランニングコストは小さく、CLI で高速
Ghostscript 変換、描画、座標情報抽出。-sDEVICE=pdfwrite で圧縮、印刷時の座標を制御できる。 高度な PDF 変換機能
MuPDF / PoDoFo C/C++ ライブラリ。高速なレンダリングとデータ抽出。 低レベル API で高い自由度
Adobe Acrobat SDK 商用ツール。JavaScript API で座標情報を操作。 公式サポート、PDF/A など対応
Tabula / Camelot 表抽出に特化。座標から領域を抽出し、CSV に変換。 ビジネスレポートの自動化に便利
pdf2text 文字列と座標を同時に取得できるユーティリティ。 スクリプト化が容易

7. 実務でよく直面する課題と解決策

7-1. 文字の回転・傾き

  • PDF の文字は 行列 で回転情報が付与される。
  • 取得した transform 行列を 2×3 行列 として扱い、座標変換関数 applyMatrix(x, y, matrix) を実装すると正確に復元できる。

7-2. 画像の座標取得

  • 画像オブジェクトは XObject として表現され、座標と拡大率が別々のプロパティに格納される。
  • PyMuPDFget_images()pix.rect を返し、直接座標が分かる。

7-3. 複数ページへの統合座標

  • PDF 内で全ページを「1枚の図」とみなす場合、ページごとの Mediabox を取得し、ページサイズを累積してオフセットを合算。

7-4. ページの回転・変換

  • rotation 属性で90°単位の回転が設定される。
  • 座標の回転を行列で変換する必要がある。

8. 具体例:あるPDFから指定領域を抽出し、ハイライトを付与

ステップ 1: 文字位置を取得

import fitz

doc = fitz.open('sample.pdf')
page = doc[0]

items = page.get_text("dict")["blocks"]
target_box = (100, 200, 300, 400)  # (x0, y0, x1, y1)

for block in items:
    if block['bbox'][1] > target_box[1] and block['bbox'][3] < target_box[3]:
        page.add_highlight_annot(block['bbox'])

ステップ 2: 画像領域を抜き出し

# 指定座標に配置された画像をファイル化
for img in page.get_images():
    xref = img[0]
    pix = fitz.Pixmap(doc, xref)
    if pix.width > 0:
        if pix.is_jpeg:
            pix.writePNG('output_' + str(xref) + '.png')

ステップ 3: スクリプトを自動化

#!/usr/bin/env bash
python3 process_pdf.py "$1"

9. まとめ:座標取得のベストプラクティス

項目 推奨手段
精度の高いテキスト座標 pdfminer.six(文字単位)
画像・図形の位置 PyMuPDFget_images()
表抽出 Camelot / Tabula
ブラウザ内で座標確認 PDF.js + textLayer
高速処理 Poppler CLI
開発環境 Python(PDF処理の統合が容易)
  1. 目的に合わせたツール選択
  2. 座標変換行列を理解(特に回転・スケールに注意)
  3. ページ・物体の単位を明確に(左下 vs 上下反転)
  4. 実装後にベンチマーク(大きいPDFの場合はスクリプトの最適化が必須)

10. さらに掘り下げたいなら

  • PyMuPDF + OpenCV で画像上の文字認識と座標対照
  • PDFBox + Apache PDFBox OCR を組み合わせ、手書き文字の座標を取得
  • Adobe PDF Services API を利用したクラウドベースの座標抽出
  • Jupyter Notebook で座標取得例をインタラクティブに確認
  • AI との組み合わせ:座標情報を元に文書分類・タグ付け

座標取得は「単なる座標数値」ではなく、文書を再構築・操作するためのです。
上記のツールとテクニックを組み合わせれば、PDF から任意の情報を正確に取得し、ビジネスプロセスの自動化に直結させることが可能になります。

ぜひ、自身のプロジェクトに合わせて試してみてください。 Happy hacking!

コメント