#始めに
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がフリーだということを考えても、日本語でも結構いい線いっていると思う