Main.java
9.67 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
package com.xly.ocr.test;
import com.benjaminwan.ocrlibrary.OcrResult;
import com.benjaminwan.ocrlibrary.Point;
import com.benjaminwan.ocrlibrary.TextBlock;
import io.github.mymonstercat.Model;
import io.github.mymonstercat.ocr.InferenceEngine;
import io.github.mymonstercat.ocr.config.ParamConfig;
import javax.imageio.ImageIO;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.awt.image.Kernel;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
public class Main {
static {
try {
String customTempDir = "D:/temp/ocrJava";
File tempDir = new File(customTempDir);
if (!tempDir.exists()) {
tempDir.mkdirs();
}
System.setProperty("java.io.tmpdir", customTempDir);
System.setProperty("TMP", customTempDir);
System.setProperty("TEMP", customTempDir);
System.setProperty("ORT_TMP_DIR", customTempDir);
System.out.println("==================================");
System.out.println("java.io.tmpdir: " + System.getProperty("java.io.tmpdir"));
System.out.println("临时目录是否存在: " + tempDir.exists());
System.out.println("==================================");
} catch (Exception e) {
System.err.println("设置临时目录失败: " + e.getMessage());
e.printStackTrace();
}
}
public static void main(String[] args) {
try {
System.out.println("OCR 程序开始执行...");
// 检查旧的临时目录
String oldTempPath = "C:\\Users\\钱豹\\AppData\\Local\\Temp\\ocrJava";
File oldTempDir = new File(oldTempPath);
if (oldTempDir.exists()) {
System.out.println("发现旧的临时目录: " + oldTempPath);
}
// 1. 初始化引擎(V4 模型)
System.out.println("正在初始化 OCR 引擎...");
InferenceEngine engine = InferenceEngine.getInstance(Model.ONNX_PPOCR_V4);
// 2. 创建优化的参数配置
ParamConfig config = createOptimizedParamConfig();
// 3. 设置图片路径
String imagePath = "E:/aa/b.jpg";
File imageFile = new File(imagePath);
if (!imageFile.exists()) {
System.err.println("图片文件不存在: " + imagePath);
return;
}
// 4. 图像预处理(可选,注释掉可提高速度)
System.out.println("正在进行图像预处理...");
String processedImagePath = preprocessImage(imagePath);
// 5. 执行识别
System.out.println("开始识别图片: " + processedImagePath);
long startTime = System.currentTimeMillis();
OcrResult ocrResult = engine.runOcr(processedImagePath, config);
long endTime = System.currentTimeMillis();
// 6. 输出识别结果
String text = ocrResult.getStrRes().trim();
System.out.println("==================================");
System.out.println("识别结果:");
System.out.println(text);
System.out.println("==================================");
System.out.println("识别耗时: " + (endTime - startTime) + " ms");
// 7. 输出文本块详细信息(可选,用于调试)
if (ocrResult.getTextBlocks() != null && !ocrResult.getTextBlocks().isEmpty()) {
System.out.println("\n文本块详情(共" + ocrResult.getTextBlocks().size() + "块):");
List<TextBlock> textBlocks = ocrResult.getTextBlocks();
for (int i = 0; i < textBlocks.size(); i++) {
TextBlock block = textBlocks.get(i);
System.out.printf(" 块%d: %s (置信度: %.2f)%n",
i + 1,
block.getText(),
block.getBoxScore()
);
}
}
// 8. 清理临时文件
if (!processedImagePath.equals(imagePath)) {
File processedFile = new File(processedImagePath);
if (processedFile.exists()) {
processedFile.delete();
System.out.println("\n已清理临时文件: " + processedImagePath);
}
}
} catch (Exception e) {
System.err.println("OCR 识别失败: " + e.getMessage());
e.printStackTrace();
}
}
private static ParamConfig createOptimizedParamConfig() {
ParamConfig config = new ParamConfig();
// 手写体专用超强参数
config.setPadding(100);
config.setMaxSideLen(1200);
// 极低阈值 = 不漏检任何手写文字
config.setBoxScoreThresh(0.25f);
config.setBoxThresh(0.15f);
config.setUnClipRatio(2.5f);
// 必须开启角度矫正
config.setDoAngle(true);
config.setMostAngle(true);
return config;
}
/**
* 图像预处理:提高OCR识别准确度
*/
private static String preprocessImage(String imagePath) throws IOException {
File inputFile = new File(imagePath);
BufferedImage originalImage = ImageIO.read(inputFile);
if (originalImage == null) return imagePath;
// 固定缩放到最佳尺寸
BufferedImage resized = resizeImageWithQuality(originalImage, 1000, 1500);
// 手写体必须:二值化(黑白强化)+ 锐化
BufferedImage binary = toBinary(resized); // 黑白强化,核心!
BufferedImage sharp = sharpenImage(binary); // 锐化
// 保存
String outputPath = imagePath.substring(0, imagePath.lastIndexOf(".")) + "_final.jpg";
ImageIO.write(sharp, "jpg", new File(outputPath));
return outputPath;
}
// 手写体专用:黑白二值化,文字瞬间清晰
private static BufferedImage toBinary(BufferedImage image) {
BufferedImage gray = new BufferedImage(image.getWidth(), image.getHeight(), BufferedImage.TYPE_BYTE_GRAY);
Graphics g = gray.getGraphics();
g.drawImage(image, 0, 0, null);
g.dispose();
// 手写体阈值 120,文字最清晰
int threshold = 120;
for (int y = 0; y < gray.getHeight(); y++) {
for (int x = 0; x < gray.getWidth(); x++) {
int rgb = gray.getRGB(x, y);
int grayValue = (rgb >> 16) & 0xFF;
if (grayValue < threshold) {
gray.setRGB(x, y, Color.BLACK.getRGB());
} else {
gray.setRGB(x, y, Color.WHITE.getRGB());
}
}
}
return gray;
}
/**
* 高质量调整图片大小
*/
private static BufferedImage resizeImageWithQuality(BufferedImage original, int maxWidth, int maxHeight) {
int width = original.getWidth();
int height = original.getHeight();
// 如果图片尺寸合适,不进行调整
if (width <= maxWidth && height <= maxHeight) {
return original;
}
// 计算缩放比例
double ratio = Math.min((double) maxWidth / width, (double) maxHeight / height);
int newWidth = (int) (width * ratio);
int newHeight = (int) (height * ratio);
// 创建缩放后的图片
BufferedImage resized = new BufferedImage(newWidth, newHeight, BufferedImage.TYPE_INT_RGB);
Graphics2D g = resized.createGraphics();
g.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BICUBIC);
g.setRenderingHint(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY);
g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
g.drawImage(original, 0, 0, newWidth, newHeight, null);
g.dispose();
System.out.println("图片已缩放: " + width + "x" + height + " -> " + newWidth + "x" + newHeight);
return resized;
}
/**
* 增强对比度
*/
private static BufferedImage enhanceContrast(BufferedImage image) {
BufferedImage result = new BufferedImage(image.getWidth(), image.getHeight(), image.getType());
for (int y = 0; y < image.getHeight(); y++) {
for (int x = 0; x < image.getWidth(); x++) {
Color color = new Color(image.getRGB(x, y));
// 增强对比度
int red = (int) (color.getRed() * 1.2);
int green = (int) (color.getGreen() * 1.2);
int blue = (int) (color.getBlue() * 1.2);
// 限制RGB值范围
red = Math.min(255, Math.max(0, red));
green = Math.min(255, Math.max(0, green));
blue = Math.min(255, Math.max(0, blue));
result.setRGB(x, y, new Color(red, green, blue).getRGB());
}
}
System.out.println("对比度已增强");
return result;
}
/**
* 锐化图像(可选,使文字边缘更清晰)
*/
private static BufferedImage sharpenImage(BufferedImage image) {
BufferedImage result = new BufferedImage(image.getWidth(), image.getHeight(), image.getType());
float[] sharpenKernel = {
0, -1, 0,
-1, 5, -1,
0, -1, 0
};
Kernel kernel = new Kernel(3, 3, sharpenKernel);
java.awt.image.ConvolveOp op = new java.awt.image.ConvolveOp(kernel, java.awt.image.ConvolveOp.EDGE_NO_OP, null);
op.filter(image, result);
System.out.println("图像已锐化");
return result;
}
}