需求:识别pdf文件中的中文
根据github项目mymonstercat 改造,先将pdf文件转为png文件存于临时文件夹,然后通过RapidOcr转为文字,最后删除临时文件夹
1、引入依赖
<dependency>
<groupId>org.apache.pdfbox</groupId>
<artifactId>fontbox</artifactId>
<version>3.0.3</version>
</dependency>
<dependency>
<groupId>org.apache.pdfbox</groupId>
<artifactId>pdfbox</artifactId>
<version>3.0.3</version>
</dependency>
<!-- ocr图片识别 -->
<dependency>
<groupId>io.github.mymonstercat</groupId>
<artifactId>rapidocr</artifactId>
<version>0.0.7</version>
</dependency>
<dependency>
<groupId>io.github.mymonstercat</groupId>
<artifactId>rapidocr-onnx-platform</artifactId>
<version>0.0.7</version>
</dependency>
<!-- 本地测试可不引 , 服务器部署linux x86架构 下引入 ,其他环境部署可搜maven -->
<dependency>
<groupId>io.github.mymonstercat</groupId>
<artifactId>rapidocr-onnx-linux-x86_64</artifactId>
<version>1.2.2</version>
</dependency>
2、工具类
import org.springframework.util.StringUtils;
import com.benjaminwan.ocrlibrary.OcrResult;
import com.benjaminwan.ocrlibrary.TextBlock;
import io.github.mymonstercat.Model;
import io.github.mymonstercat.ocr.InferenceEngine;
import org.apache.pdfbox.Loader;
import org.apache.pdfbox.pdmodel.PDDocument;
import org.apache.pdfbox.rendering.PDFRenderer;
import org.springframework.stereotype.Service;
import javax.imageio.ImageIO;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.nio.file.*;
import java.nio.file.attribute.BasicFileAttributes;
import java.util.ArrayList;
import java.util.Base64;
import java.util.List;
import java.util.UUID;
@Service
public class PdfOCRConverter {
//临时输出png文件路径
private static final String outputDirs = "D:/pdfToImg/temp/";
public static void main(String[] args) throws IOException {
List<String> fileNameList = getWords("D:/Download/123.pdf");
for (String fileName : fileNameList) {
System.out.println(fileName);
}
}
public static List<String> getWords(String pdfFilePath) throws IOException {
String outputDir = outputDirs + UUID.randomUUID().toString().replace("-", "");
List<String> fileNameList = convertPdfToImage(pdfFilePath, outputDir);
List<String> wordsList = new ArrayList<>();
for (String fileName : fileNameList) {
System.out.println("识别图片:"+fileName);
if (StringUtils.isEmpty(fileName)){break;}
List<String> words = runOcr(fileName);
for (String word : words) {
System.out.println(word);
wordsList.add(word);
}
}
deleteDirectory(outputDir);
return wordsList;
}
public static List<String> runOcr(String path) {
List<String> results = new ArrayList<>();
InferenceEngine engine = InferenceEngine.getInstance(Model.ONNX_PPOCR_V3);
OcrResult ocrResult = engine.runOcr(path);
for (TextBlock textBlock : ocrResult.getTextBlocks()) {
results.add(textBlock.getText());
}
return results;
}
public static List<String> convertPdfToImage(String pdfFilePath, String outputDir) {
// 设置DPI(越高图片越清晰,但文件也会更大)
int dpi = 300;
List<String> fileNameList = new ArrayList<>();
File file = new File(pdfFilePath);
try (PDDocument document = Loader.loadPDF(file)) {
PDFRenderer pdfRenderer = new PDFRenderer(document);
String pdfFileName = file.getName().replace(".pdf", "");
String name = pdfFileName;
for (int page = 0; page < document.getNumberOfPages(); page++) {
BufferedImage bim = pdfRenderer.renderImageWithDPI(page, dpi);
String folder = createFolder(outputDir + "/" + name);
String fileName = folder + "/" + pdfFileName + "_page_" + (page + 1) + ".png";
ImageIO.write(bim, "png", new File(fileName));
fileNameList.add(fileName);
System.out.println("生成图片:"+fileName);
}
} catch (IOException e) {
e.printStackTrace();
}
return fileNameList;
}
public static void deleteDirectory(String path) throws IOException {
// 如果路径不指向一个目录,则抛出异常
Path directory = Paths.get(path);
if (!Files.isDirectory(directory)) {
throw new IOException("The provided path is not a directory.");
}
// 遍历目录中的所有文件和子目录
Files.walkFileTree(directory, new SimpleFileVisitor<Path>() {
@Override
public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException {
// 删除文件
Files.delete(file);
return FileVisitResult.CONTINUE;
}
@Override
public FileVisitResult postVisitDirectory(Path dir, IOException exc) throws IOException {
// 所有内容被删除后删除目录本身
Files.delete(dir);
return FileVisitResult.CONTINUE;
}
@Override
public FileVisitResult visitFileFailed(Path file, IOException exc) throws IOException {
// 如果访问文件失败,则抛出异常
throw exc;
}
});
}
public static String createFolder(String folderPath) {
String txt = folderPath;
try {
File myFilePath = new File(txt);
txt = folderPath;
if (!myFilePath.exists()) {
myFilePath.mkdirs();
}
} catch (Exception e) {
e.printStackTrace();
}
return txt;
}
public static List<String> getWordsByBase64(String base64) throws IOException {
List<String> words = new ArrayList<>();
if (StringUtils.isEmpty(base64)) {
return null;
}
String outputDir = outputDirs + UUID.randomUUID().toString().replace("-", "");
// 解码Base64字符串
byte[] decodedBytes = Base64.getDecoder().decode(base64);
createFolder(outputDir);
// 输出的PDF文件名
String outputFilePath = outputDir+"/output.pdf";
try (FileOutputStream fos = new FileOutputStream(outputFilePath)) {
// 将解码后的字节数组写入文件
fos.write(decodedBytes);
System.out.println("PDF文件已成功生成: " + outputFilePath);
words = getWords(outputFilePath);
} catch (Exception e) {
e.printStackTrace();
}
deleteDirectory(outputDir);
return words;
}
}