座標取得の基礎知識
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として表現され、座標と拡大率が別々のプロパティに格納される。 PyMuPDFのget_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(文字単位) |
| 画像・図形の位置 | PyMuPDF(get_images()) |
| 表抽出 | Camelot / Tabula |
| ブラウザ内で座標確認 | PDF.js + textLayer |
| 高速処理 | Poppler CLI |
| 開発環境 | Python(PDF処理の統合が容易) |
- 目的に合わせたツール選択
- 座標変換行列を理解(特に回転・スケールに注意)
- ページ・物体の単位を明確に(左下 vs 上下反転)
- 実装後にベンチマーク(大きいPDFの場合はスクリプトの最適化が必須)
10. さらに掘り下げたいなら
- PyMuPDF + OpenCV で画像上の文字認識と座標対照
- PDFBox + Apache PDFBox OCR を組み合わせ、手書き文字の座標を取得
- Adobe PDF Services API を利用したクラウドベースの座標抽出
- Jupyter Notebook で座標取得例をインタラクティブに確認
- AI との組み合わせ:座標情報を元に文書分類・タグ付け
座標取得は「単なる座標数値」ではなく、文書を再構築・操作するための鍵です。
上記のツールとテクニックを組み合わせれば、PDF から任意の情報を正確に取得し、ビジネスプロセスの自動化に直結させることが可能になります。
ぜひ、自身のプロジェクトに合わせて試してみてください。 Happy hacking!


コメント