JiaJiaOCR:Java 开源 OCR 识别库
在 OCR 技术落地过程中,Java 开发者常面临 Python 生态繁荣但 Java 集成困难的困境。JiaJiaOCR 提供轻量级和全功能版本,支持通用 OCR、手写 OCR、版面检测及表格识别。
版本说明
| 版本 | 大小 | 核心功能 | 适用场景 |
|---|---|---|---|
| 轻量版 (1.0+) | 21MB+ | 通用 OCR 识别 | 快速集成、资源受限环境 |
| 全功能版 (2.0+) | 200MB+ | 通用 OCR+ 手写 OCR+ 版面检测 + 表格识别 | 企业级应用、复杂文档处理 |
版本更新
轻量版 (1.0+)
- v1.0.1: 优化英文 OCR 空白识别,返回空串而非 null
- v1.0.2: 新增 PDF 识别支持
全功能版 (2.0+)
- v2.0.1: 优化英文 OCR 空白识别,返回空串而非 null
- v2.0.2: 新增 PDF 识别支持
- 性能提升:模型懒加载机制,按需加载
- 功能扩容:新增手写 OCR、版面检测、表格检测与识别
- 结果升级:新增版面元素坐标、表格 HTML 格式输出
核心功能
- 通用 OCR:支持中英文、数字、符号混合识别,适用于发票、标签等印刷体场景。
- 手写 OCR:针对中文手写体专项优化,支持工整及连笔手写,识别准确率达 92% 以上。
- 版面检测:自动识别标题、段落、图片、表格等元素,返回坐标与类型标签。
- 表格检测与识别:纯 Java 表格识别方案,支持区域检测、单元格分割,输出 HTML 格式结构化结果。
快速上手
环境准备
- 开发环境:JDK 8 及以上
- 运行环境:Windows 10+、Linux x86_64
- 依赖管理:Maven
引入依赖
Maven 依赖
<dependencies>
<dependency>
<groupId>com.microsoft.onnxruntime</groupId>
<artifactId>onnxruntime</artifactId>
<version>1.19.0</version>
</dependency>
<dependency>
<groupId>ai.djl.mxnet</groupId>
<artifactId>mxnet-engine</artifactId>
<version>0.31.0</version>
</dependency>
<dependency>
<groupId>ai.djl.opencv</groupId>
<artifactId>opencv</artifactId>
<version>0.31.0</version>
</dependency>
<dependency>
<groupId>ai.djl</groupId>
<artifactId>api</artifactId>
<version>0.31.0</version>
</dependency>
<dependency>
<groupId>org.apache.pdfbox</groupId>
<artifactId>pdfbox</artifactId>
<version>3.0.2</version>
</dependency>
</dependencies>
下载 Jar 包
前往 GitHub 仓库 releases 页面下载 JiaJiaOCR jar 包并放入项目依赖目录。该 Jar 包集成了模型文件。
代码示例
import com.jiajia.common_object.*;
import com.jiajia.core.JiaJiaOCR;
import org.apache.commons.lang3.tuple.Pair;
import org.opencv.core.Mat;
import org.opencv.core.Point;
import org.opencv.imgcodecs.Imgcodecs;
import org.opencv.imgproc.Imgproc;
import java.util.ArrayList;
import java.util.List;
import static com.jiajia.common_object.PdfConvert.convertPdfToImages;
public class JiaJiaOCR2Demo {
public static void main(String... args) {
String imgPath = "test.jpg";
// generalOCRTest(imgPath);
// handwrittingOCRTest(imgPath);
// layoutDetTest(imgPath);
// tableDetTest(imgPath);
// tableRecTest(imgPath);
// tableDetRecTest(imgPath);
// textLineDetText(imgPath);
// pdfOCR();
}
public static void generalOCRTest(String imgPath) {
JiaJiaOCR jiaJiaOCR = JiaJiaOCR.builder();
List<Pair<Text, Box>> result = jiaJiaOCR.recognizeGeneralText(imgPath);
System.out.println("通用 OCR 结果:" + result);
}
public static void handwrittingOCRTest(String imgPath) {
JiaJiaOCR jiaJiaOCR = JiaJiaOCR.builder();
List<Pair<Text, Box>> result = jiaJiaOCR.recognizeHandwrittenText(imgPath);
System.out.println("手写 OCR 结果:" + result);
}
public static void layoutDetTest(String imgPath) {
JiaJiaOCR jiaJiaOCR = JiaJiaOCR.builder();
List<Layout> layoutList = jiaJiaOCR.detectLayout(imgPath);
Mat img = Imgcodecs.imread(imgPath);
drawLayoutPredictions(img, layoutList);
Imgcodecs.imwrite("layout_result.jpg", img);
System.out.println("版面检测结果已保存:" + layoutList);
}
public static void tableDetTest(String imgPath) {
JiaJiaOCR jiaJiaOCR = JiaJiaOCR.builder();
List<DetectionResult> tableList = jiaJiaOCR.detectTables(imgPath);
Mat img = Imgcodecs.imread(imgPath);
Mat resultMat = drawTableResults(img, tableList);
Imgcodecs.imwrite("table_detect_result.jpg", resultMat);
System.out.println("表格检测区域:" + tableList);
}
public static void tableRecTest(String imgPath) {
JiaJiaOCR jiaJiaOCR = JiaJiaOCR.builder();
List<Pair<Text, Box>> ocrResult = jiaJiaOCR.recognizeGeneralText(imgPath);
TableResult tableResult = jiaJiaOCR.recognizeTableFromOCR(imgPath, ocrResult);
System.out.println("表格识别 HTML 结果:" + tableResult.getHtmlContent());
}
public static void tableDetRecTest(String imgPath) {
JiaJiaOCR jiaJiaOCR = JiaJiaOCR.builder();
List<TableResult> tableResults = jiaJiaOCR.recognizeTables(imgPath);
for (TableResult table : tableResults) {
System.out.println("表格 HTML:" + table.getHtmlContent());
System.out.println("表格坐标:" + table.getBox());
}
}
public static void textLineDetText(String imgPath) {
JiaJiaOCR jiaJiaOCR = JiaJiaOCR.builder();
Boxes textLines = jiaJiaOCR.detectTextLines(imgPath);
Mat img = Imgcodecs.imread(imgPath);
drawTextLinePredictions(img, textLines);
Imgcodecs.imwrite("textline_result.jpg", img);
System.out.println("文本行检测结果:" + textLines);
}
public static void pdfOCR() throws IOException, OrtException {
String pdfPath = "How_To.pdf";
String pdfOutputDir = "pdf_image";
JiaJiaOCR jiaJiaOCR = JiaJiaOCR.builder();
List<String> pdfPathList = convertPdfToImages(pdfPath, pdfOutputDir);
for (String pdfImgPath : pdfPathList) {
List<Pair<Text, Box>> pairList = jiaJiaOCR.recognizeGeneralText(pdfImgPath);
System.out.println(pairList);
}
}
public static void drawLayoutPredictions(Mat img, List<Layout> detLayout) {
for (Layout layout : detLayout) {
int[] bbox = layout.getBbox();
Imgproc.rectangle(img, new Point(bbox[0], bbox[1]), new Point(bbox[2], bbox[3]), new Scalar(0, 0, 255), 2);
String label = layout.getLabel();
Imgproc.putText(img, label, new Point(bbox[0] + 5, bbox[1] - 10), Imgproc.FONT_HERSHEY_SIMPLEX, 0.7, new Scalar(0, 255, 0), 2);
}
}
public static Mat drawTableResults(Mat image, List<DetectionResult> results) {
Mat resultImg = image.clone();
for (DetectionResult result : results) {
String label = "表格:" + String.format("%.2f", result.getConfidence());
Imgproc.putText(resultImg, label, new Point(result.getRect().x, result.getRect().y - 10), Imgproc.FONT_HERSHEY_SIMPLEX, 1.0, new Scalar(0, 0, 255), 2);
Imgproc.rectangle(resultImg, new Point(result.getRect().x, result.getRect().y), new Point(result.getRect().x + result.getRect().width, result.getRect().y + result.getRect().height), new Scalar(0, 0, 255), 2);
}
return resultImg;
}
public static void drawTextLinePredictions(Mat img, Boxes detBoxes) {
List<Box> boxList = detBoxes.getBoxes();
for (Box box : boxList) {
double[] pos = box.getLinePosition();
Point[] points = new Point[4];
points[0] = new Point(pos[0], pos[1]);
points[1] = new Point(pos[2], pos[3]);
points[2] = new Point(pos[4], pos[5]);
points[3] = new Point(pos[6], pos[7]);
MatOfPoint polygon = new MatOfPoint(points);
List<MatOfPoint> polygons = new ArrayList<>();
polygons.add(polygon);
Imgproc.polylines(img, polygons, true, new Scalar(0, 0, 255), 1);
}
}
}
关键返回结果
| 功能模块 | 核心返回内容 | 数据格式说明 |
|---|---|---|
| 通用 OCR / 手写 OCR | 文本内容、坐标、置信度 | List<Pair<Text, Box>> |
| 版面检测 | 元素类型、坐标、置信度 | List |
| 表格检测 | 表格区域、置信度 | List |
| 表格识别 | 表格结构、内容、坐标 | TableResult |
效果展示
通用 OCR 效果

手写 OCR 效果

版面检测效果

表格检测效果

表格识别效果

