adbird(広告鳥) 備忘録

記事一覧・このブログの主要カテゴリー

記事一覧

ブログ(無料版)の仕様で、デフォルトのトップページだと投稿記事の1つ1つが全部表示されてしまい、ブログ全体を把握しづらい。下記のリンクから入ったほうが記事を探しやすいかも。このブログをブックマークする際も下記リンクをブックマークすることをオススメする。

最近よく更新するカテゴリーなど。

複数ページあるPDFの全ページ一括切り抜き

各ページのレイアウトが全て同じのPDFデータから、全てのページ、特定の範囲だけ切り抜きたい(トリミングしたい)ときに便利。

ChatGPTさんに考えてもらった。

下準備

pythonをインストール。自分で調べて。

pymupdfライブラリをインストール。

pip install pymupdf

切り取る範囲を確認

PDFをGimpで開き(開くのは1ページ分だけで良い)、切り取る左上座標と右下座標を確認。

※PDFを開く際に、解像度を300ピクセルにして開く

一括切り抜き

pdfcrop.pyスクリプトを実行。スクリプトの内容は後述の通り。

python3 pdfcrop.py input.pdf output.pdf 100 600 2300 2800

※上記は、切り取る座標が左上(100 , 600)、右下(2300 , 2800)の場合。

pdfcropp.py

import sys
import fitz

# 使い方:
# python pdfcrop.py input.pdf output.pdf x1 y1 x2 y2 [dpi]

if len(sys.argv) not in (7, 8):
    print("Usage:")
    print("  python pdfcrop.py input.pdf output.pdf x1 y1 x2 y2 [dpi]")
    sys.exit(1)

input_pdf = sys.argv[1]
output_pdf = sys.argv[2]

# 300dpi画像上で確認した座標(px)
x1 = int(sys.argv[3])
y1 = int(sys.argv[4])
x2 = int(sys.argv[5])
y2 = int(sys.argv[6])

# dpi省略時は300
dpi = int(sys.argv[7]) if len(sys.argv) == 8 else 300

# px → PDF内部座標(pt)
scale = 72 / dpi

rect = fitz.Rect(
    x1 * scale,
    y1 * scale,
    x2 * scale,
    y2 * scale
)

doc = fitz.open(input_pdf)

for page in doc:
    page.set_cropbox(rect)

doc.save(output_pdf)

print(f"Saved: {output_pdf}")

カレントディレクトリでCygwinを開く方法

ほとんど参照リンクのとおり。

cygwinでchereをインストール。

管理者権限でcygwinを起動して、以下を実行。

chere -i -s bash -e "Cygwin Here(&B)" -t mintty

エクスプローラーで右クリック>その他のオプションを確認>「Cygwin Here(B)」というメニューが入っているはず。

または、エクスプローラーで Shift + 右クリック>「Cygwin Here(B)」。

NDLOCR-LiteでOCRして、透明テキストの付いたPDFを作成(端末だけで実行ver2)

※以前の記事(NDLOCR-LiteでOCRして、透明テキストの付いたPDFを作成(端末だけで実行))の方法で、コマンドライン(Powershell)のみでできるようにしたが、実行には複数回コマンドを打たなければいけなかった。

今回の記事では、コマンドを打つ回数は1回で、さらに画像の傾きの自動補正(斜めになっているのをまっすぐにする)工程を追加したスクリプトとなっている(Geminiに作成してもらった)。

※ただし、縦書きOCRでしか試していないので、横書きOCRがうまく機能するかは試していないので、あしからず。


国立国会図書館(NDL)がGPUを必要としないOCRツール NDLOCR-Liteアプリケーション を公開した。 https://github.com/ndl-lab/ndlocr-lite

これを利用すると、紙ベースで書類等をスキャンしたPDFデータをOCRできるだけでなく、PDFに透明テキストをつけることができる。

下準備

1. Pythonのインストール・各種ライブラリのインストール

初心者がPythonを入れるのは、Microsoft Storeからインストールのが一番楽だと思うのだが、Store版は一部ツールとの相性が良くないらしいので、公式版をインストールしたほうがいいらしい。下記サイトを参照に。

なお、NDLOCR-Liteのコマンドラインから操作を行うにはPython 3.10以上が必要とのこと。
それ以上のバージョンでできるだけ最新のものをインストールしておけば大丈夫だとは思う…。

Pythonをインストール後、別途各種ライブラリを、Powershellで以下を実行してインストール。

pip install pymupdf reportlab pillow

2.ImageMagickのインストール

Windowsの場合

Powershellで以下を実行でインストール。

winget install --id=ImageMagick.ImageMagick 

Macの場合

ターミナルで

brew install imagemagick 

Linux(Ubuntu)の場合

sudo apt install imagemagick 

3.NDLOCR-Lite ダウンロード・pythonモジュールのインストール

  • NDLOCR-Liteアプリケーションのリポジトリのリリースページより、右上の緑の「Code」>Download zip でzipファイルをダウンロードして展開するか、gitでダウンロード。
    • ※リリースされたばかりでバージョンアップが激しいので、こまめにリリースを確認する
  • Zipを展開したできたフォルダを日本語(全角文字)を含まない場所に配置
    • NDLOCR-Liteの使い方に「デスクトップアプリケーションを利用する際には、日本語(全角文字)を含まないパスにアプリケーションを配置してください。全角文字を含む場合に起動しないことがあります。」という注意事項がある。
  • 「コマンドラインからの利用」をよく読んで、必要なpythonモジュール(pip install -r requirements.txtのところ)をインストール。
    • pip install -r requirements.txtがうまく行かないときは、いろいろ自分で頑張って…。

4. スクリプト(ocr_pdf_txt.py)を作成

Geminiに作ってもらった。※縦書きOCRでしか試していないので、横書きOCRがうまく機能するかは試していないので、あしからず。

メモ帳などのテキストエディタで以下の内容を ocr_pdf_txt.py として保存。

ただし、16行目のC:\YOUR_PATH\ndlocr-lite-master\srcの部分(NDLOCR-Liteのocr.pyが入っているフォルダ)は、自分の環境に合わせて書き換える

import os
import sys
import glob
import json
import time
import subprocess
import shutil
import fitz  # PyMuPDF
from PIL import Image
from reportlab.pdfgen import canvas
from reportlab.pdfbase import pdfmetrics
from reportlab.pdfbase.cidfonts import UnicodeCIDFont
from reportlab.lib.colors import blue

# --- 設定項目 ---
NDLOCR_REPO_PATH = os.path.abspath(r"C:\YOUR_PATH\ndlocr-lite-master\src")
# ----------------

def create_pdf_from_json(json_path, img_path, output_path):
    """個別PDF生成ロジック(ReportLab)"""
    try:
        with open(json_path, 'r', encoding='utf-8') as f:
            data = json.load(f)
        img = Image.open(img_path)
        img_w, img_h = img.size
        c = canvas.Canvas(output_path, pagesize=(img_w, img_h))
        pdfmetrics.registerFont(UnicodeCIDFont('HeiseiMin-W3', isVertical=True))
        pdfmetrics.registerFont(UnicodeCIDFont('HeiseiKakuGo-W5', isVertical=False))
        c.drawImage(img_path, 0, 0, width=img_w, height=img_h)
        c.setFillColor(blue, alpha=0.0)

        contents = data.get('contents', [[]])[0] if 'contents' in data else []
        for item in contents:
            text = item.get('text', '')
            bbox = item.get('boundingBox', [])
            if not text or not bbox: continue
            x_coords = [p[0] for p in bbox]; y_coords = [p[1] for p in bbox]
            x_min, x_max = min(x_coords), max(x_coords); y_min, y_max = min(y_coords), max(y_coords)
            width, height = x_max - x_min, y_max - y_min
            if height > width:
                font_size = width * 0.7
                x_pdf, y_pdf = x_max - (font_size * 0.7), img_h - y_min
                c.setFont('HeiseiMin-W3', font_size)
                c.drawString(x_pdf, y_pdf, text)
            else:
                font_size = height * 0.7
                x_pdf, y_pdf = x_min, img_h - y_max
                c.setFont('HeiseiKakuGo-W5', font_size)
                c.drawString(x_pdf, y_pdf, text)
        c.save()
        return True
    except Exception as e:
        print(f"Error: {e}"); return False

def main():
    if len(sys.argv) < 2:
        print("使用法: python makeTXT_PDF.py 入力.pdf"); return

    input_pdf = os.path.abspath(sys.argv[1])
    output_name = os.path.splitext(os.path.basename(input_pdf))[0]
    
    current_dir = os.getcwd()
    target_dir = os.path.join(current_dir, "OCR", "image")
    abs_pdf_dir = os.path.join(current_dir, "OCR", "OCR_PDF")
    abs_txt_dir = os.path.join(current_dir, "OCR", "OCR_TXT")

    for d in [target_dir, abs_pdf_dir, abs_txt_dir]:
        os.makedirs(d, exist_ok=True)

    try:
        # 1. PDF -> PNG (PyMuPDF)
        print("--- 1. PDFを画像に変換中 ---")
        doc_orig = fitz.open(input_pdf)
        for i, page in enumerate(doc_orig):
            pix = page.get_pixmap(matrix=fitz.Matrix(2, 2))
            pix.save(os.path.join(target_dir, f"image-{i+1:03d}.png"))
        doc_orig.close()

        # 追加工程: ImageMagick による傾き補正
        print("--- 1b. 画像の傾きを補正中 (ImageMagick) ---")
        # Windows環境で *.png を正しく処理するため shell=True を使用
        subprocess.run("mogrify -deskew 50% *.png", shell=True, cwd=target_dir, check=True)

        # 2. NDLOCR-Lite 実行
        print("--- 2. NDLOCR-Lite 実行中 ---")
        subprocess.run([
            sys.executable, os.path.join(NDLOCR_REPO_PATH, "ocr.py"),
            "--sourcedir", target_dir,
            "--output", target_dir
        ], cwd=NDLOCR_REPO_PATH, check=True)
        
        time.sleep(2)

        # 3. 個別PDF生成
        print("--- 3. 個別PDF生成とテキスト抽出 ---")
        json_files = sorted(glob.glob(os.path.join(target_dir, "image-*.json")))
        full_text = ""
        for json_file in json_files:
            base = os.path.splitext(os.path.basename(json_file))[0]
            img_file = os.path.join(target_dir, f"{base}.png")
            pdf_page_out = os.path.join(target_dir, f"{base}.pdf")
            txt_file = os.path.join(target_dir, f"{base}.txt")
            if os.path.exists(img_file): create_pdf_from_json(json_file, img_file, pdf_page_out)
            if os.path.exists(txt_file):
                with open(txt_file, 'r', encoding='utf-8') as f: full_text += f.read() + "\n\n"

        # 4. PDFの結合 (PyMuPDF)
        print(f"--- 4. PDFを結合中: {output_name}.pdf ---")
        combined_pdf = fitz.open()
        page_pdfs = sorted(glob.glob(os.path.join(target_dir, "image-*.pdf")))
        for p_pdf in page_pdfs:
            with fitz.open(p_pdf) as m_pdf: combined_pdf.insert_pdf(m_pdf)
        
        combined_pdf_path = os.path.join(abs_pdf_dir, f"{output_name}.pdf")
        combined_pdf.save(combined_pdf_path)
        combined_pdf.close()

        # 5. テキスト保存
        with open(os.path.join(abs_txt_dir, f"{output_name}.txt"), "w", encoding="utf-8") as f:
            f.write(full_text)

        print(f"\n完了しました!\n出力: {combined_pdf_path}")

    except Exception as e:
        print(f"エラー: {e}")
    finally:
        # 中間ファイルの削除
        shutil.rmtree(target_dir, ignore_errors=True)
        pass

if __name__ == "__main__":
    main()

5. ディレクトリ構成

ディレクトリ(フォルダ)構成を以下のようにする。

任意ディレクトリ
 ├─入力.pdf
 └─ocr_pdf_txt.py

スクリプトを実行すると自動的に任意ディレクトリの下位ディレクトリにOCRフォルダ、さらに下位ディレクトリにimageフォルダ、OCR_PDFフォルダ、OCR_TXTフォルダを配置してくれる。

実行

PDFやocr_pdf_txt.pyが入っているフォルダ内で右クリック、「ターミナルで開く」でPowerShellを起動。以下を実行。 pdfが各ページごとのpngファイルに変換され、OCR>imageフォルダに入る。

python3 ocr_pdf_txt.py "入力.pdf"

入力.pdfのところは、ドラッグ&ドロップでパス付きファイル名を入れないように。ファイル名をだけを入れること。

OCRフォルダ内の、OCR_PDFフォルダに透明テキスト付PDFが、OCR_TXTフォルダに結合されたテキストファイルが入っているはず。

さらに、たとえばOCRしたいPDFが、1922.01.pdf、1922.02.pdf … のように連番で存在して、それらを一気にOCRしたい場合は、Powershellで以下のようにする。

Get-ChildItem 1922.*.pdf | Sort-Object Name | ForEach-Object {python3 ocr_pdf_txt.py $_.Name}

おまけ:テキスト内のキーワード検索

「OCR-TXT」フォルダ内の全てのtxtファイルを対象に、一瞬でキーワード検索できる。
「OCR-TXT」フォルダ内で右クリック、「ターミナルで開く」でPowerShellを起動。以下のように実行。

Windowsの場合

Select-String "検索したいキーワード" *.txt | Format-Table Filename, LineNumber, Line

and検索の例

Select-String "師範學校" *.txt | Select-String "鹿兒島" | Format-Table Filename,LineNumber,Line

MacやLinuxの場合

grep --color=always -n -H "検索したいキーワード" *.txt | column -t -s ":"

and検索の例

grep --color=always -n -H "師範學校" *.txt | grep --color=always -n -H "鹿兒島" | column -t -s ":"

余談

ターミナルのフォントはUDEV Gothicを使うと良い。
yuru7/udev-gothic: UDEV Gothic

NDLOCR-LiteでOCRして、透明テキストの付いたPDFを作成(端末だけで実行)

※追記:もっと簡単に実行できるように改良した(Geminiに改良してもらった)。

NDLOCR-LiteでOCRして、透明テキストの付いたPDFを作成(端末だけで実行ver2)


国立国会図書館(NDL)がGPUを必要としないOCRツール NDLOCR-Liteアプリケーション を公開した。 https://github.com/ndl-lab/ndlocr-lite

これを利用すると、紙ベースで書類等をスキャンしたPDFデータをOCRできるだけでなく、PDFに透明テキストをつけることができる。

※以前の記事(NDLOCR-LiteでOCRして、透明テキストの付いたPDFを作成)の方法は、コマンドライン(Powershell)とNDLOCR-LiteのGUIを行ったり来たりしながらやらないといけなかったので、今回はコマンドラインのみでできるようにする。

※ただし、縦書きOCRでしか試していないので、横書きOCRがうまく機能するかは試していないので、あしからず。

下準備

1.NDLOCR-Lite ダウンロード

  • NDLOCR-Liteアプリケーションのリポジトリのリリースページより、右上の緑の「Code」>Download zip でzipファイルをダウンロードして展開するか、gitでダウンロード。
    • ※リリースされたばかりでバージョンアップが激しいので、こまめにリリースを確認する
  • Zipを展開したできたフォルダを日本語(全角文字)を含まない場所に配置
    • NDLOCR-Liteの使い方に「デスクトップアプリケーションを利用する際には、日本語(全角文字)を含まないパスにアプリケーションを配置してください。全角文字を含む場合に起動しないことがあります。」という注意事項がある。
  • 「コマンドラインからの利用」を読んで、必要なpythonモジュール(pip install -r requirements.txtのところ)をインストール。
    • pip install -r requirements.txtがうまく行かないときは、いろいろ自分で頑張って…。

2.PDFTKのインストール

Windowsの場合

Powershellで以下を実行でインストール。

winget install --id=PDFLabs.PDFtk.Server 

Macの場合

ターミナルで

brew install pdftk-java 

Linux(Ubuntu)の場合

sudo apt install pdftk-java 

3. python、PyMuPDFライブラリのインストール

初心者がpythonを入れるのは、PCのMicrosoft Storeからインストールのが一番楽だと思う。

PyMuPDFライブラリは、Powershellで以下を実行してインストール。

pip install pymupdf

4. PDFをpngにするスクリプト(pdftopng.py)を作成

PDFを各ページごとのpng画像にするためのスクリプト。なお、ChatGPTに作ってもらった。

メモ帳などのテキストエディタで以下の内容を pdftopng.py として保存。

import sys
import os
import fitz
from multiprocessing import Pool, cpu_count

def convert_pages(args):
    pdf_path, pages, outdir = args

    doc = fitz.open(pdf_path)

    for page_num in pages:
        page = doc.load_page(page_num)
        pix = page.get_pixmap(matrix=fitz.Matrix(2,2), alpha=False)
        pix.save(f"{outdir}/image-{page_num+1:04d}.png")

    doc.close()

def main():

    if len(sys.argv) < 2:
        print("使い方: python3 pdftopng.py ファイル名.pdf")
        sys.exit()

    pdf = sys.argv[1]

    if not pdf.lower().endswith(".pdf"):
        pdf += ".pdf"

    outdir = os.path.join("OCR", "image")
    os.makedirs(outdir, exist_ok=True)

    doc = fitz.open(pdf)
    total_pages = len(doc)
    doc.close()

    cores = cpu_count()

    page_lists = [[] for _ in range(cores)]
    for i in range(total_pages):
        page_lists[i % cores].append(i)

    tasks = [(pdf, pages, outdir) for pages in page_lists if pages]

    with Pool(cores) as p:
        p.map(convert_pages, tasks)

if __name__ == "__main__":
    main()

5. PDFにJSONファイルの文字情報を重ねたり、PDFやテキストを結合するなどのスクリプト(makeOCR_PDF.py)を作成

メモ帳などのテキストエディタで、以下の内容を「makeOCR_PDF.py」として保存。
これはGeminiに作成してもらった。 ※ただし、縦書きOCRでしか試していないので、横書きOCRがうまく機能するかは試していないので、あしからず。

import json
import os
import sys
import glob
import subprocess
from PIL import Image
from reportlab.pdfgen import canvas
from reportlab.pdfbase import pdfmetrics
from reportlab.pdfbase.cidfonts import UnicodeCIDFont
from reportlab.lib.colors import blue

# --- 基本設定 ---
TARGET_DIR = './OCR/image/'
# 親ディレクトリ基準の保存先
PDF_FINAL_DIR = '../OCR_PDF/'
TXT_FINAL_DIR = '../OCR_TXT/'

def create_pdf_from_json(json_path, img_path, output_path):
    """個別PDF生成ロジック"""
    try:
        with open(json_path, 'r', encoding='utf-8') as f:
            data = json.load(f)
        img = Image.open(img_path)
        img_w, img_h = img.size
        c = canvas.Canvas(output_path, pagesize=(img_w, img_h))
        pdfmetrics.registerFont(UnicodeCIDFont('HeiseiMin-W3', isVertical=True))
        pdfmetrics.registerFont(UnicodeCIDFont('HeiseiKakuGo-W5', isVertical=False))
        c.drawImage(img_path, 0, 0, width=img_w, height=img_h)
        c.setFillColor(blue, alpha=0.0) # 透明設定

        for item in data['contents'][0]:
            text = item['text']
            bbox = item['boundingBox']
            x_coords = [p[0] for p in bbox]; y_coords = [p[1] for p in bbox]
            x_min, x_max = min(x_coords), max(x_coords)
            y_min, y_max = min(y_coords), max(y_coords)
            width, height = x_max - x_min, y_max - y_min

            if height > width: # 縦書き
                font_size = width * 0.7
                x_pdf = x_max - (font_size * 0.7)
                y_pdf = img_h - y_min
                c.setFont('HeiseiMin-W3', font_size)
                c.drawString(x_pdf, y_pdf, text)
            else: # 横書き
                font_size = height * 0.7
                x_pdf = x_min
                y_pdf = img_h - y_max
                c.setFont('HeiseiKakuGo-W5', font_size)
                c.drawString(x_pdf, y_pdf, text)
        c.save()
        return True
    except Exception as e:
        print(f"Error: {e}")
        return False

def main():
    # 1. 引数のチェック
    if len(sys.argv) < 2:
        print("使用法: python3 make.py [出力ファイル名]")
        print("例: python3 make.py sample_01")
        return

    output_name = sys.argv[1] # コマンドラインからの引数

    # 保存先ディレクトリの準備
    abs_pdf_dir = os.path.abspath(os.path.join(TARGET_DIR, PDF_FINAL_DIR))
    abs_txt_dir = os.path.abspath(os.path.join(TARGET_DIR, TXT_FINAL_DIR))
    os.makedirs(abs_pdf_dir, exist_ok=True)
    os.makedirs(abs_txt_dir, exist_ok=True)

    # 2. 個別PDFの生成
    json_files = sorted(glob.glob(os.path.join(TARGET_DIR, "image-*.json")))
    if not json_files:
        print("対象ファイルが見つかりません。")
        return

    for json_file in json_files:
        base = os.path.splitext(os.path.basename(json_file))[0]
        img_file = os.path.join(TARGET_DIR, f"{base}.png")
        pdf_out = os.path.join(TARGET_DIR, f"{base}.pdf")
        if os.path.exists(img_file):
            create_pdf_from_json(json_file, img_file, pdf_out)

    # 3. PDFの結合 (pdftk)
    print(f"PDFを結合中: {output_name}.pdf")
    combined_pdf_path = os.path.join(abs_pdf_dir, f"{output_name}.pdf")
    subprocess.run(f"pdftk *.pdf cat output \"{combined_pdf_path}\"", shell=True, cwd=TARGET_DIR)

    # 4. テキストの結合 (PowerShell)
    print(f"テキストを結合中: {output_name}.txt")
    combined_txt_path = os.path.join(abs_txt_dir, f"{output_name}.txt")
    ps_command = f'Get-Content -Encoding UTF8 .\\*.txt | Out-File -FilePath "{combined_txt_path}" -Encoding UTF8'
    subprocess.run(["powershell", "-Command", ps_command], cwd=TARGET_DIR)

    # 5. 後片付け (削除)
    print("中間ファイルを削除中...")
    extensions = ['*.pdf', '*.txt', '*.png', '*.json', '*.xml']
    for ext in extensions:
        for f in glob.glob(os.path.join(TARGET_DIR, ext)):
            os.remove(f)

    print(f"完了しました。出力先:\n PDF: {combined_pdf_path}\n TXT: {combined_txt_path}")

if __name__ == "__main__":
    main()

6. ディレクトリ構成

ディレクトリ(フォルダ)構成を以下のようにする。

任意ディレクトリ
 ├─入力.pdf
 ├─pdftopng.py
 ├─makeOCR_PDF.py
 └─OCR
    ├─image
    ├─OCR_PDF
    └─OCR_TXT

任意ディレクトリにOCRをしたいPDF、pdftopng.py、makeOCR_PDF.pyを入れ、
その下位ディレクトリにOCRフォルダ、
さらに下位ディレクトリにimageフォルダ、OCR_PDFフォルダ、OCR_TXTフォルダを配置する。

作業手順

1.PDF→png

PDFやpdftopng.pyが入っているフォルダ内で右クリック、「ターミナルで開く」でPowerShellを起動。以下を実行。 pdfが各ページごとのpngファイルに変換され、OCR>imageフォルダに入る。

python3 pdftopng.py "入力.pdf"

"入力.pdf"のところは、""(ダブルクォーテーションマーク)の中にカーソルを持ってきて、pdfファイルをドラッグ・アンド・ドロップをすればよい。

2.NDLOCR-LiteでOCR

ターゲットフォルダ(--sourcedir)OCR>imageフォルダで、出力データ保存先(--output)も同じOCR>imageフォルダで、OCR。

python3 "D:\D_Program_Files\ndlocr-lite-master\src\ocr.py" --sourcedir "D:\Documents\test\OCR\image" --output "D:\Documents\test\OCR\image"

D:\D_Program_Files\ndlocr-lite-master\src\ocr.pyD:\Documents\test\OCR\imageのところは、自分の環境に合わせて適宜修正を。

3.PDFにJSONファイルの文字情報を重ねたり、PDFやテキストを結合するなど

OCR後、以下を実行。

OCR_PDFフォルダに透明テキスト付PDFが、OCR_TXTフォルダに結合されたテキストファイルが入って、imageフォルダ内のpdf、txt、png、json、xmlファイルが削除される。

python3 makeOCR_PDF.py 出力ファイル名

おまけ:テキスト内のキーワード検索

「OCR-TXT」フォルダ内の全てのtxtファイルを対象に、一瞬でキーワード検索できる。
「OCR-TXT」フォルダ内で右クリック、「ターミナルで開く」でPowerShellを起動。以下のように実行。

Windowsの場合

Select-String "検索したいキーワード" *.txt | Format-Table Filename, LineNumber, Line

and検索の例

Select-String "師範學校" *.txt | Select-String "鹿兒島" | Format-Table Filename,LineNumber,Line

MacやLinuxの場合

grep --color=always -n -H "検索したいキーワード" *.txt | column -t -s ":"

and検索の例

grep --color=always -n -H "師範學校" *.txt | grep --color=always -n -H "鹿兒島" | column -t -s ":"

余談

ターミナルのフォントはUDEV Gothicを使うと良い。
yuru7/udev-gothic: UDEV Gothic

Vivaldiの検索フィールドを表示させる方法

Vivaldiでは以前は、検索フィールドがデフォルトで表示されていたのに、今は非表示になっているようだ。
個人的には検索フィールドがないと不便なのでデフォルトで表示しておいてほしい。
いつも表示させる方法を忘れてしまう…。

左上のVivaldiアイコン > 表示 > ツールバーをカスタマイズ > ツールバーエディター で

「検索フィールド」のアイコンをドラッグ&ドロップで、アドレスバーに追加。

NDLOCR-LiteでOCRして、透明テキストの付いたPDFを作成

国立国会図書館(NDL)がGPUを必要としないOCRツール NDLOCR-Liteアプリケーション を公開した。 https://github.com/ndl-lab/ndlocr-lite

これを利用すると、紙ベースで書類等をスキャンしたPDFデータをOCRできるだけでなく、PDFに透明テキストをつけることができる。

下準備

1.NDLOCR-Lite ダウンロード

  • NDLOCR-Liteアプリケーションのリポジトリのリリースページより、アプリケーションファイル(Windowsの場合はzip)をダウンロード。
    ダウンロード後、右クリックして展開。
    • ※リリースされたばかりでバージョンアップが激しいので、こまめにリリースを確認する
  • Zipを展開したできたフォルダを日本語(全角文字)を含まない場所に配置
    • NDLOCR-Liteの使い方に「デスクトップアプリケーションを利用する際には、日本語(全角文字)を含まないパスにアプリケーションを配置してください。全角文字を含む場合に起動しないことがあります。」という注意事項がある。

2.PDFTKのインストール

Windowsの場合

Powershellで以下を実行でインストール。

winget install --id=PDFLabs.PDFtk.Server 

Macの場合

ターミナルで

brew install pdftk-java 

Linux(Ubuntu)の場合

sudo apt install pdftk-java 

3. python、PyMuPDFライブラリのインストール

初心者がpythonを入れるのは、PCのMicrosoft Storeからインストールのが一番楽だと思う。

PyMuPDFライブラリは、Powershellで以下を実行してインストール。

pip install pymupdf

4. pyhton スクリプト(pdftopng.py)作成

PDFを各ページごとのpng画像にするためのスクリプト。なお、ChatGPTに作ってもらった。

メモ帳などのテキストエディタで以下の内容を pdftopng.py として保存。

import sys
import os
import fitz
from multiprocessing import Pool, cpu_count

def convert_pages(args):
    pdf_path, pages, outdir = args

    doc = fitz.open(pdf_path)

    for page_num in pages:
        page = doc.load_page(page_num)
        pix = page.get_pixmap(matrix=fitz.Matrix(2,2), alpha=False)
        pix.save(f"{outdir}/image-{page_num+1:04d}.png")

    doc.close()

def main():

    if len(sys.argv) < 2:
        print("使い方: python3 pdftopng.py ファイル名.pdf")
        sys.exit()

    pdf = sys.argv[1]

    if not pdf.lower().endswith(".pdf"):
        pdf += ".pdf"

    outdir = os.path.join("OCR", "image")
    os.makedirs(outdir, exist_ok=True)

    doc = fitz.open(pdf)
    total_pages = len(doc)
    doc.close()

    cores = cpu_count()

    page_lists = [[] for _ in range(cores)]
    for i in range(total_pages):
        page_lists[i % cores].append(i)

    tasks = [(pdf, pages, outdir) for pages in page_lists if pages]

    with Pool(cores) as p:
        p.map(convert_pages, tasks)

if __name__ == "__main__":
    main()

5. PDFやテキストを結合などするスクリプトを作成

結合.bat 作成(Windowsの場合)

メモ帳などのテキストエディタで、以下の内容を「結合.bat」として保存。

cd OCR/image
pdftk *.pdf cat output ..\OCR_PDF\%1.pdf
powershell -Command "Get-Content -Encoding UTF8 .\*.txt | Out-File -FilePath ..\OCR_TXT\%1.txt -Encoding UTF8"
rm *.pdf
rm *.txt
rm *.png

結合.sh 作成(Linuxの場合。Macでも?)

メモ帳などのテキストエディタで、以下の内容を「結合.sh」として保存。

cd OCR/image
pdftk *.pdf cat output ../OCR_PDF/$1.pdf
cat *.txt > ../OCR_TXT/$1.txt
rm *.pdf
rm *.txt
rm *.png

6. ディレクトリ構成

ディレクトリ(フォルダ)構成を以下のようにする。

任意ディレクトリ
 ├─入力.pdf
 ├─pdftopng.py
 ├─結合.bat
 └─OCR
    ├─image
    ├─OCR_PDF
    └─OCR_TXT

任意ディレクトリにOCRをしたいPDF、pdftopng.py、結合.bat(Linux、macの場合は、結合.sh)を入れ、
その下位ディレクトリにOCRフォルダ、
さらに下位ディレクトリにimageフォルダ、OCR_PDFフォルダ、OCR_TXTフォルダを配置する。

作業手順

1.PDF→png

PDFやpdftopng.pyが入っているフォルダ内で右クリック、「ターミナルで開く」でPowerShellを起動。以下を実行。 pdfが各ページごとのpngファイルに変換され、OCR>imageフォルダに入る。

python3 pdftopng.py "入力.pdf"

"入力.pdf"のところは、""(ダブルクォーテーションマーク)の中にカーソルを持ってきて、pdfファイルをドラッグ・アンド・ドロップをすればよい。

2.NDLOCR-LiteでOCR

  • NDLOCR-Liteを起動(前述のフォルダ内の「ndlocr_lite_gui.exe」をダブルクリックで起動。 )
    • 初回だけ「WindowsによってPCが保護されました」→「詳細情報」→「実行」。
    • アプリのウィンドウが起動しても、ウィンドウの中身がなかなか表示されないが気長に待つ(特に初回)。
    • 一度起動さえすれば、タスクバーに表示されたアイコン上で右クリック>「タスクバーにピン留めする」をしておけば便利。
  • 「フォルダ内の画像を処理する」をクリックして、「image」フォルダを指定する。
    • 「image」フォルダ内は事前に空になっていることを確認する。
  • 「出力先を選択する」をクリックして、同じ「image」フォルダを指定。
  • 「出力形式の選択」をクリックして、以下のように設定する。(適宜、必要に応じてチェックを入れる)
    • 「認識箇所の可視化画像を保存する」のチェックを外す。
    • 「出力形式の選択」 > 「TXT形式」と「透明テキスト付PDF(ベータ)」にチェックを入れる。
    • それ以外のチェックを外す。
  • 「OCR」をクリック。
    • PC能力によるが、ページ数が多いと、そこそこ時間がかかる。

3.PDFやTXTを結合

OCR後、以下を実行。

OCR_PDFフォルダに透明テキスト付PDFが、OCR_TXTフォルダに結合されたテキストファイルが入って、imageフォルダ内のpdf、txt、pngファイルが削除される。

Windowsの場合

./結合.bat 出力ファイル名

※出力ファイル名に拡張子(.txtや.pdf)はつけない

Linuxの場合

sh 結合.sh 出力ファイル名

おまけ:テキスト内のキーワード検索

「OCR-TXT」フォルダ内の全てのtxtファイルを対象に、一瞬でキーワード検索できる。
「OCR-TXT」フォルダ内で右クリック、「ターミナルで開く」でPowerShellを起動。以下のように実行。

Windowsの場合

Select-String "検索したいキーワード" *.txt | Format-Table Filename, LineNumber, Line

and検索の例

Select-String "師範學校" *.txt | Select-String "鹿兒島" | Format-Table Filename,LineNumber,Line

MacやLinuxの場合

grep --color=always -n -H "検索したいキーワード" *.txt | column -t -s ":"

and検索の例

grep --color=always -n -H "師範學校" *.txt | grep --color=always -n -H "鹿兒島" | column -t -s ":"

余談

ターミナルのフォントはUDEV Gothicを使うと良い。
yuru7/udev-gothic: UDEV Gothic