LoginSignup
0
0

PDF 上の領域を PNG に切り出す (+ PDF 上の文章と図を列挙する)

Posted at

PDF 上の領域を PNG ファイルに切り出すだけです。
やっていることは、pdf2image によって対象ページの画素の Numpy 配列を得て、ほしい領域にスライスして、PNG ファイルにかきだしているだけです。

主な用途として、pdfminer.six と組み合わせて利用することを想定しています (「経緯とおまけ」を参照)。

スクリプト

以下で out.png が切り出せます。
動作確認したい場合は https://arxiv.org/pdf/2302.11939 をダウンロードして隣に置いて実行すれば 2 ページ目の図が切り出されると思います。

from pdf2image import convert_from_path
# Pillow か cv2 のどちらかあればよいが pdf2image が Pillow 依存のため Pillow のほうがよかった
from PIL import Image
# import cv2
import numpy as np


# PDF の指定のページの指定の座標を PNG に切り取ります
def extract_image_from_pdf(
    pdf_file_path,  # 入力 PDF ファイルパス
    i_page,  # 何ページ目か (最初のページが 1 ページ)
    width, height,  # ある座標系でのページ横幅とページ縦幅
    x0, x1, y0, y1,  # その座標系での切取領域 (ページ左下が原点)
    out_path='out.png',  # 出力 PNG ファイルパス
):
    pdf_imgs = convert_from_path(
        pdf_file_path, first_page=i_page, last_page=i_page)
    img_arr = np.asarray(pdf_imgs[0])
    height_ = img_arr.shape[0]
    width_ = img_arr.shape[1]
    left = int(width_ * (x0 / width))
    right = int(width_ * (x1 / width))
    top = int(height_ * (1.0 - y1 / height))
    bottom = int(height_ * (1.0 - y0 / height))

    # PIL の場合
    im = Image.fromarray(img_arr[top:bottom, left:right])
    im.save(out_path)

    # OpenCV の場合: RGB --> BGR にする必要があるため逆順にしてかきだす
    # cv2.imwrite(out_path, img_arr[top:bottom, left:right, ::-1])


extract_image_from_pdf(
    '2302.11939v6.pdf', 2, 612, 792,
    147.59897250019998, 497.5777438482, 497.2811145825, 727.2735377315)

経緯とおまけ ( pdfminer.six で PDF 上の要素を列挙する)

pdfminer.six は PDF の各ページのどこの座標にどんな文章や図があるかを解析してくれるパッケージです。が、図の扱いはややこしいと思います。

というのは、対象ページ LTPage 以下に LTImage オブジェクトがぶらさがっていればそれを画像ファイル化できますが ( python - Pdf miner how to extract images - Stack Overflow )、対象ページ中の図が必ずしも LTImage として取得できずに線 (LTLine) や曲線 (LTCurve) の集合になっていることがあります (この記事のスクリプトで抜き出した絵はそうなっています=LTFigure 以下に LTImage がないです) (同じ PDF 内でも LTImage として取り出せる図もあります) (なお、LTLine や LTCurve が簡単に画像ファイル化できないのかはよく調べていません)。

なので、pdfminer.six によって図を抽出するのはあきらめて、LTFigure 領域をみつけたらそのページの画素からその部分の画素を切り取ることにしました。そうすると下のキャプチャのように、左側の PDF ページから、右側のような「このページのどこに図と文章がある」という情報を列挙できます。

image.png

上のキャプチャのスクリプトは以下のノートブックの 2 セル目です (Gist には画像は表示されません)。なお、このスクリプトは LTPage 直下の LTTextBox と LTFigure しか抽出しません。
https://gist.github.com/CookieBox26/e4b3c83f728a421760ebb81faf7a24f8

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0