22
Help us understand the problem. What are the problem?

More than 3 years have passed since last update.

posted at

updated at

JavaでPDFファイルをOCR処理してみた

始めに

PDFに含まれているイメージファイルをOCR処理するJavaのプログラムを書いてみた
当初はpythonで実装しようとしたが、使用するライブラリの依存関係が意味わからめだったので、仕方なく使い慣れたJavaで実装することにした

使用したライブラリ

工夫した点などなど

  • PDFの解析のサンプルプログラムはどれもループ使いすぎてソースが見づらかったので、自分はmapとreduceを駆使してみて書いてみたよ
  • Iteratorからstreamへの変換はもっとスマートな方法がないものだろうか・・・

ソース

PDFからイメージを取得するクラス

PDFmaker.java
package pdf;

import java.io.File;
import java.nio.charset.Charset;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.nio.file.StandardOpenOption;
import java.util.Spliterator;
import java.util.Spliterators;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import java.util.stream.StreamSupport;

import org.apache.pdfbox.cos.COSName;
import org.apache.pdfbox.pdmodel.PDDocument;
import org.apache.pdfbox.pdmodel.PDPage;
import org.apache.pdfbox.pdmodel.PDResources;
import org.apache.pdfbox.pdmodel.graphics.PDXObject;
import org.apache.pdfbox.pdmodel.graphics.image.PDImageXObject;

public class PDFMaker {
    public static void main(String args[])throws Exception{
        //読み込むPDFファイル
        PDDocument document = PDDocument.load(new File("C:/python/img/pdf/2017h29a_sc_pm2_qs.pdf"));
        //PDFページを処理する
        Stream<PDPage>stream = StreamSupport.stream(Spliterators.spliteratorUnknownSize(
                document.getDocumentCatalog().getPages().iterator(),
                        Spliterator.ORDERED),false);

        System.out.println("start");
        Files.write(Paths.get("parse.txt"), 
                stream.map(s->exePDFpage(s)).collect(Collectors.toList()), 
                Charset.forName("MS932"),
                StandardOpenOption.CREATE);
        System.out.println("end");
    }

    //PDFのPageを処理する
    public static String exePDFpage(PDPage p){
        Stream<COSName>stream = StreamSupport.stream(Spliterators.spliteratorUnknownSize(
                p.getResources().getXObjectNames().iterator(),Spliterator.ORDERED),false);
        return stream.map(s->exeImage(s,p.getResources()))
        .reduce((s,v)->s+v).get();
    }

    //PDFのPageをJpgに変換する
    public static String exeImage(COSName n,PDResources resources){
        try{
            PDXObject xobject = resources.getXObject(n);
            if(xobject instanceof PDImageXObject){
                PDImageXObject image2 = (PDImageXObject) resources.getXObject(n);
                return PDFtoImg.extractFromPDF(image2.getImage());
            }
            return "";
        }catch(Exception e){
            e.printStackTrace();
            return "";
        }   
    }
}

イメージファイルをOCR読み込みする処理

PDFtoImg.java
package pdf;

import java.awt.image.BufferedImage;

import net.sourceforge.tess4j.ITesseract;
import net.sourceforge.tess4j.Tesseract;
import net.sourceforge.tess4j.TesseractException;

public class PDFtoImg {
    private static final String  DICTIONARY_PATH ="C:/Users/takayoshi/workspace/PDF/tessdata";
    public static String extractFromPDF(BufferedImage img) {
        ITesseract instance = new Tesseract();
        try {
            instance.setLanguage("jpn");
            instance.setDatapath(DICTIONARY_PATH);
            String result = instance.doOCR(img);
            return result;
        } catch (TesseractException ex) {
            ex.printStackTrace();
            return "";
        }
    }
}

感想

  • 情報処理技術者試験の情報処理安全確保支援士試験(SC)の問題を改正するのに大体10分~20分くらいかかる
  • 最初の1ページ目の解析結果は以下の通り
平成 29 年度 秋期
{ ニ `
情報処理女全確保支援士試験
ノ
午後 = 問題
試験時聞 ー4:30 ~ ー6:30 (2 時間)
注意事項
ー・ 試験開始及び終了は, 監督員の時計が基準です。 監督員の指示に従つてく だ さい〟
2~ 試験開始の合図がある まで, 問題冊子を開いて中を見てはいけません。
3~ 答案用紙への受験番号などの記入は, 試験開始の合図がぁってから始めてください。
4_ 問題は, 吹の表に従つて解答してください。

OCRがフリーだということを考えても、日本語でも結構いい線いっていると思う

Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Sign upLogin
22
Help us understand the problem. What are the problem?