1.1.2 指定矩形からテキストを抽出

1-1-第2項指定矩形からテキストを抽出

狙い・効果

指定矩形からテキストを抽出します。

処理の概要

テキスト抽出する矩形を指定し、指定したページ番号のContent内のテキストを抽出して1.1.1 ページから全テキスト抽出と同じ形式でテキストファイルとして出力します。テキストが矩形とどの位重なっていたら抽出対象とするかを0.0から1.0の小数値で指定し、ActualTextを無視するか否かも指定します。ここで扱われるActualTextとは、例えば異体字のような文字の置き換え用途で使われる要素で、文字が鴎(U+9D0E)となっていてもActualTextの設定があり鷗(U+9DD7)となっていたら鷗(U+9DD7)が抽出されます。無視するよう指定することで鴎(U+9D0E)が抽出されます。

PDF Tool APIの主な機能

PtlParamExtractText.APIappendRect(PtlRect rectMM): テキスト抽出する矩形を追加

PtlParamExtractText.APIsetTextOverlapRatio(float overlapRatio): テキストが矩形とどれくらい重なっていたら抽出対象とするかを設定

PtlParamExtractText.APIsetIgnoreActualText(boolean ignoreActualText): ActualTextを無視するかを設定

プログラム例

package cookbook;

import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.BufferedWriter;
import java.io.PrintWriter;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.nio.charset.Charset;

import jp.co.antenna.ptl.*;

public class ExtractTextSetRect {
    // そのクラスのusageを表示する関数
    private static void printUsage(){
        System.out.println("usage: java ExtractTextSetRect in-pdf-file out-text-file" + 
                           " page-to-extract overlap-ratio ignore-actual-text");
        System.out.println("ignore-actual-text:");
        System.out.println("0:ActualTextを無視しない 1:ActualTextを無視する");

    }

    /**
     * @param args the command line arguments
     */
    public static void main(String[] args) {
        if (args.length < 5)
        {
            printUsage(); // usageメッセージの表示
            return;
        }
        // コマンドライン引数の読み取り・判定
        // 出力PDFの名前はあとで渡すためにString型で保存する。
        String outputTextURI = args[1];
        int pageToExtract = Integer.parseInt(args[2]);
        float overlapRatio = Float.parseFloat(args[3]);
        boolean ignoreActualText = true;
        try
        {
            ignoreActualText = readBoolArgs(args[4],
                                       "ignore-actual-textは1か0で指定してください。");

        }
        catch (IllegalArgumentException ex) {
            System.out.println(ex.getMessage());
            printUsage(); // usageメッセージの表示
            return;
        }

        try (PtlParamInput inputFile = new PtlParamInput(args[0]);
             PtlPDFDocument doc = new PtlPDFDocument();
             BufferedReader br = new BufferedReader(new InputStreamReader(System.in)))
        {
            // PDFファイルをロード
            doc.load(inputFile);
            //ページ数を取得
            int wholePageNum = doc.getPageCount();
            //pageToExtractのエラー処理
            if(wholePageNum < pageToExtract)
            {
                System.out.println("ERROR: page-to-extractはPDFの総ページ数より"+
                                   "小さい値を指定してください。");
                System.out.println("総ページ数:" + wholePageNum);
                printUsage();
                return;
            }

            try (PtlPages pages = doc.getPages()) //ページコンテナの取得
            {
                // ページコンテナが空かどうか
                if (pages.isEmpty())
                {
                    System.out.println("ERROR : ページコンテナが空");
                    return;
                }

                // ページの取得(パラメータindexは0が先頭のため1を引く)
                try (PtlPage page = pages.get(pageToExtract - 1);
                     // ページコンテントの取得
                     PtlContent content = page.getContent();
                     // 文字抽出のパラメータクラス。
                     PtlParamExtractText paramExtractText = new PtlParamExtractText())
                {
                    // テキスト抽出する矩形を指定
                    paramExtractText.appendRect(setRectCoordinate(br));
                    // テキストが矩形とどのくらい重なっていれば抽出するか設定
                    paramExtractText.setTextOverlapRatio(overlapRatio);
                    // ActialTextを無視するかどうか
                    paramExtractText.setIgnoreActualText(ignoreActualText);
                    // 文字列抽出
                    String TextFromPdf = content.extractText(paramExtractText);
                    // 文字列の出力
                    outputTextFile(outputTextURI, TextFromPdf);
                    System.out.println(TextFromPdf);
                }
            }            
        }

	...【ExtractText.javaと同じ処理のため省略
	 ・エラーメッセージ処理と出力】...

    }

    /**
     * テキストファイルを出力するための関数。 
     * 出力エンコードはシステムのデフォルト値を利用する。
     * 特に外部からの呼び出しを想定しないためprivateとする。
     * 
     * @param outputTextURI 出力ファイルのURI。
     * @param TextFromPdf 出力したいString型変数
     */
    private static void outputTextFile(String outputTextURI, String TextFromPdf){

	...【ExtractText.javaと同じ処理のため省略】...

    }

    /**
     * 矩形の各値を入力してその座標値をもつ矩形を返す関数。
     * 原点はPDFの左下端。
     * bottomよりtopが大きい、leftよりもrightが大きいなどの矛盾した数値は入力できない。
     * 特に外部からの呼び出しを想定しないためprivateとする。
     * 
     * @param br BufferedReader。数値の読み取りに使う。
     * @return 指定したleft, bottom, right, topの数値を持つPtlRect
     */
    private static PtlRect setRectCoordinate(BufferedReader br)
        throws IOException, PtlException, Exception, Error
    {
        float top, bottom, left, right;
        boolean isValueOkay = false;
        PtlRect outputRect = new PtlRect();
        while(!isValueOkay)
        {
            System.out.println("配置矩形の各数値を入力してください。");
            System.out.print("top (mm) : ");
            top = Float.parseFloat(br.readLine());
            System.out.print("bottom (mm) : ");
            bottom = Float.parseFloat(br.readLine());
            if(top < bottom)
            {
                System.out.println("topの値はbottomよりも大きい値を指定して" +
                                   "再度入力してください。");
                continue;
            }
            System.out.print("left (mm) : ");
            left = Float.parseFloat(br.readLine());
            System.out.print("right (mm) : ");
            right = Float.parseFloat(br.readLine());
            if(right < left)
            {
                System.out.println("rightの値はleftよりも大きい値を指定して" +
                                   "再度入力してください。");
                continue;
            }

            //矩形を正しく指定できた場合の処理
            isValueOkay = true;
            outputRect.setLeft(left);
            outputRect.setBottom(bottom);
            outputRect.setRight(right);
            outputRect.setTop(top);
        }                   
        return outputRect;
    }

    /**
     * 0または1を入力されたargsにより、trueまたはfalseを返すメソッド。
     * 
     * @param args 与えられるコマンドライン引数。0または1でtrueまたはfalseを指定する。
     * @param errorMessage argsが0か1でなかった場合に出力されるエラーメッセージを指定する。
     * @return argsの数値を読み取った結果を戻す
     * @throws java.lang.IllegalArgumentException argsが0か1でなかった場合に発生。
     */
    public static boolean readBoolArgs(String args, String errorMessage)
        throws IllegalArgumentException
    {
        boolean trueOrFalse = false;

        // argsの読み取り
        switch(args){
        case "0":
            trueOrFalse = false;
            break;
        case "1":
            trueOrFalse = true;
            break;
        default:
            throw new IllegalArgumentException(errorMessage);
        }
        return trueOrFalse;
    }
}

プログラムファイル名

ExtractTextSetRect.java

入出力操作の例

C:\samples>java cookbook.ExtractTextSetRect 
usage: java ExtractTextSetRect in-pdf-file out-text-file page-to-extract overlap-ratio ignore-actual-text

C:\samples>java cookbook.ExtractTextSetRect novelText.pdf outputTextSetRect.txt 1 0.6 1 
配置矩形の各数値を入力してください。
top (mm) : 200
bottom (mm) : 150
left (mm) : 40
right (mm) : 90

Output text URI :outputTextSetRect.txt

wondering, almost with en
nd in any extremity inclin, 
Cain’s heresy,’ he used to 
In this character, it was fr
ece and the last good influe
ng as they came about his c
-- 完了 --

novelText.pdfの1ページ目で、指定した矩形領域(枠で囲った範囲)のテキストを抽出してoutputTextSetRect.txtファイルに保存します。

1.1.2 指定矩形からテキストを抽出

【注意】出力されるテキストファイルには改行は入りません。入出力操作の例を理解しやすくするため、本書の編集で入力したものです。