Skip to content

Commit 235a6cd

Browse files
authored
Merge pull request #69 from litongjava/master
release to v2.2.9
2 parents 2e3820d + 6d57eba commit 235a6cd

File tree

17 files changed

+379
-222
lines changed

17 files changed

+379
-222
lines changed

docs/cn/1 快速上手/1.0 快速上手.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -92,7 +92,7 @@ mvn clean package -DskipTests
9292
以下是一个基本的 `jpackage` 命令示例,用于将 JavaFX JAR 打包为 `.exe` 文件:
9393

9494
```bash
95-
jpackage --type exe --input target/ --main-jar tool-ocr-1.2.6.jar --name tree-hole-ocr --main-class com.luooqi.ocr.MainFm
95+
jpackage --type exe --input target/ --main-jar tool-ocr-1.2.6.jar --name tree-hole-ocr --main-class com.luooqi.ocr.OcrApp
9696
```
9797

9898
其中:

pom.xml

+23-17
Original file line numberDiff line numberDiff line change
@@ -6,14 +6,14 @@
66

77
<groupId>com.luooqi</groupId>
88
<artifactId>tools-ocr</artifactId>
9-
<version>2.2.8</version>
9+
<version>2.2.9</version>
1010

1111
<properties>
1212
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
1313
<java.version>1.8</java.version>
1414
<maven.compiler.source>${java.version}</maven.compiler.source>
1515
<maven.compiler.target>${java.version}</maven.compiler.target>
16-
<main.class>com.luooqi.ocr.MainFm</main.class>
16+
<main.class>com.luooqi.ocr.OcrApp</main.class>
1717
<lombok.version>1.18.20</lombok.version>
1818
<logback.version>1.2.3</logback.version>
1919
<djl.version>0.25.0</djl.version>
@@ -39,6 +39,12 @@
3939
<version>4.2</version>
4040
</dependency>
4141

42+
<dependency>
43+
<groupId>org.apache.pdfbox</groupId>
44+
<artifactId>pdfbox</artifactId>
45+
<version>2.0.24</version>
46+
</dependency>
47+
4248
<dependency>
4349
<groupId>org.projectlombok</groupId>
4450
<artifactId>lombok</artifactId>
@@ -96,21 +102,21 @@
96102
</dependency>
97103
<!-- GraalVM - Java Fx -->
98104
<!-- https://mvnrepository.com/artifact/org.openjfx/javafx-controls -->
99-
<!-- <dependency>-->
100-
<!-- <groupId>org.openjfx</groupId>-->
101-
<!-- <artifactId>javafx-controls</artifactId>-->
102-
<!-- <version>17</version>-->
103-
<!-- </dependency>-->
104-
<!-- <dependency>-->
105-
<!-- <groupId>org.openjfx</groupId>-->
106-
<!-- <artifactId>javafx-swing</artifactId>-->
107-
<!-- <version>17</version>-->
108-
<!-- </dependency>-->
109-
<!-- <dependency>-->
110-
<!-- <groupId>org.openjfx</groupId>-->
111-
<!-- <artifactId>javafx-fxml</artifactId>-->
112-
<!-- <version>17</version>-->
113-
<!-- </dependency>-->
105+
<!-- <dependency>-->
106+
<!-- <groupId>org.openjfx</groupId>-->
107+
<!-- <artifactId>javafx-controls</artifactId>-->
108+
<!-- <version>17</version>-->
109+
<!-- </dependency>-->
110+
<!-- <dependency>-->
111+
<!-- <groupId>org.openjfx</groupId>-->
112+
<!-- <artifactId>javafx-swing</artifactId>-->
113+
<!-- <version>17</version>-->
114+
<!-- </dependency>-->
115+
<!-- <dependency>-->
116+
<!-- <groupId>org.openjfx</groupId>-->
117+
<!-- <artifactId>javafx-fxml</artifactId>-->
118+
<!-- <version>17</version>-->
119+
<!-- </dependency>-->
114120

115121

116122
<!--windows gpu-->

readme.md

+4
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,9 @@
88
- onnx
99
- paddle ocr
1010
- opencv
11+
12+
## 开源地址
13+
[gitee](https://gitee.com/ppnt/tools-ocr) | [github](https://github.com/litongjava/tools-ocr)
1114
## 安装
1215
> - **安装路径请勿包含中文字符**
1316
> - 本程序使用 JavaFX 开发,提供的安装包中已经包含了Java
@@ -49,6 +52,7 @@ mvn jfx:native -DskipTests -f pom.xml
4952
![2](readme_files/2.jpg)
5053

5154
## TODO
55+
- [x] PDF识别
5256
- [x] 图片文字识别
5357
- [x] 识别结果文本对齐(暂未实现多分栏)
5458
- [x] 全屏模式下截图

src/main/java/com/litongjava/djl/paddle/ocr/v4/detection/OCRDetectionTranslator.java

+19-11
Original file line numberDiff line numberDiff line change
@@ -104,18 +104,20 @@ public NDList processOutput(TranslatorContext ctx, NDList list) {
104104
srcMat.release();
105105
}
106106

107+
NDList dt_boxes = null;
107108
NDArray boxes = boxes_from_bitmap(manager, pred, newMask);
109+
if (boxes != null) {
110+
//boxes[:, :, 0] = boxes[:, :, 0] / ratio_w
111+
NDArray boxes1 = boxes.get(":, :, 0").div(ratio_w);
112+
boxes.set(new NDIndex(":, :, 0"), boxes1);
113+
//boxes[:, :, 1] = boxes[:, :, 1] / ratio_h
114+
NDArray boxes2 = boxes.get(":, :, 1").div(ratio_h);
115+
boxes.set(new NDIndex(":, :, 1"), boxes2);
108116

109-
//boxes[:, :, 0] = boxes[:, :, 0] / ratio_w
110-
NDArray boxes1 = boxes.get(":, :, 0").div(ratio_w);
111-
boxes.set(new NDIndex(":, :, 0"), boxes1);
112-
//boxes[:, :, 1] = boxes[:, :, 1] / ratio_h
113-
NDArray boxes2 = boxes.get(":, :, 1").div(ratio_h);
114-
boxes.set(new NDIndex(":, :, 1"), boxes2);
117+
dt_boxes = this.filter_tag_det_res(boxes);
115118

116-
NDList dt_boxes = this.filter_tag_det_res(boxes);
117-
118-
dt_boxes.detach();
119+
dt_boxes.detach();
120+
}
119121

120122
// release Mat
121123
newMask.release();
@@ -255,12 +257,18 @@ private NDArray boxes_from_bitmap(NDManager manager, NDArray pred, Mat bitmap) {
255257
newContour.release();
256258
}
257259

258-
NDArray boxes = NDArrays.stack(boxList);
259-
260260
// release
261261
hierarchy.release();
262262

263+
NDArray boxes = null;
264+
if (boxList.size() > 0) {
265+
boxes = NDArrays.stack(boxList);
266+
return boxes;
267+
}
268+
263269
return boxes;
270+
271+
264272
}
265273

266274
/**

src/main/java/com/litongjava/djl/paddle/ocr/v4/recognition/OcrV4Recognition.java

+3
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,9 @@ public List<RotatedBox> predict(NDManager manager,
6464
Image image, Predictor<Image, NDList> detector, Predictor<Image, String> recognizer)
6565
throws TranslateException {
6666
NDList boxes = detector.predict(image);
67+
if (boxes == null) {
68+
return null;
69+
}
6770
// 交给 NDManager自动管理内存
6871
// attach to manager for automatic memory management
6972
boxes.attach(manager);
+40
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
package com.luooqi.ocr;
2+
3+
import cn.hutool.core.thread.GlobalThreadPool;
4+
import com.luooqi.ocr.config.InitConfig;
5+
import com.luooqi.ocr.local.PaddlePaddleOCRV4;
6+
import com.luooqi.ocr.windows.MainForm;
7+
import javafx.application.Application;
8+
import javafx.stage.Stage;
9+
import lombok.extern.slf4j.Slf4j;
10+
import org.jnativehook.GlobalScreen;
11+
12+
@Slf4j
13+
public class OcrApp extends Application {
14+
15+
public static void main(String[] args) {
16+
launch(args);
17+
}
18+
19+
@Override
20+
public void init() throws Exception {
21+
super.init();
22+
InitConfig.init();
23+
}
24+
25+
26+
@Override
27+
public void start(Stage primaryStage) {
28+
MainForm mainForm = new MainForm();
29+
mainForm.init(primaryStage);
30+
primaryStage.show();
31+
}
32+
33+
@Override
34+
public void stop() throws Exception {
35+
log.info("close");
36+
GlobalScreen.unregisterNativeHook();
37+
PaddlePaddleOCRV4.INSTANCE.close();
38+
GlobalThreadPool.shutdown(true);
39+
}
40+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
package com.luooqi.ocr.constants;
2+
3+
/**
4+
* Created by [email protected] on 12/9/2023_7:14 PM
5+
*/
6+
public class ImagesConstants {
7+
public static final String LOGO = "img/logo.png";
8+
}

src/main/java/com/luooqi/ocr/local/LocalOCR.java

-49
This file was deleted.

src/main/java/com/luooqi/ocr/local/PaddlePaddleOCRV4.java

+13
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
import ai.djl.repository.zoo.ModelNotFoundException;
1010
import ai.djl.repository.zoo.ModelZoo;
1111
import ai.djl.repository.zoo.ZooModel;
12+
import ai.djl.translate.TranslateException;
1213
import com.litongjava.djl.paddle.ocr.v4.common.RotatedBox;
1314
import com.litongjava.djl.paddle.ocr.v4.common.RotatedBoxCompX;
1415
import com.litongjava.djl.paddle.ocr.v4.detection.OcrV4Detection;
@@ -62,7 +63,14 @@ public void init() {
6263
public String ocr(File imageFile) throws Exception {
6364
Path path = imageFile.toPath();
6465
Image image = OpenCVImageFactory.getInstance().fromFile(path);
66+
return ocr(image);
67+
}
68+
69+
public String ocr(Image image) throws Exception {
6570
List<RotatedBox> detections = recognition.predict(manager, image, detector, recognizer);
71+
if (detections == null) {
72+
return null;
73+
}
6674

6775
List<RotatedBox> initList = new ArrayList<>();
6876
for (RotatedBox result : detections) {
@@ -105,4 +113,9 @@ public String ocr(File imageFile) throws Exception {
105113
}
106114
return fullText.toString();
107115
}
116+
117+
public void close() {
118+
detector.close();
119+
recognizer.close();
120+
}
108121
}

src/main/java/com/luooqi/ocr/snap/ScreenCapture.java

+19-17
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,9 @@
33

44
import cn.hutool.core.swing.ScreenUtil;
55
import cn.hutool.log.StaticLog;
6-
import com.luooqi.ocr.MainFm;
76
import com.luooqi.ocr.model.CaptureInfo;
87
import com.luooqi.ocr.utils.CommUtils;
8+
import com.luooqi.ocr.windows.MainForm;
99
import javafx.animation.AnimationTimer;
1010
import javafx.application.Platform;
1111
import javafx.embed.swing.SwingFXUtils;
@@ -180,8 +180,7 @@ public ScreenCapture(Stage mainStage) {
180180

181181
mainCanvas.setOnMouseDragged(m -> {
182182
if (m.getButton() == MouseButton.PRIMARY) {
183-
if (m.getScreenX() >= CaptureInfo.ScreenMinX &&
184-
m.getScreenX() <= CaptureInfo.ScreenMaxX) {
183+
if (m.getScreenX() >= CaptureInfo.ScreenMinX && m.getScreenX() <= CaptureInfo.ScreenMaxX) {
185184
data.mouseXNow = (int) m.getX();
186185
} else if (m.getScreenX() > CaptureInfo.ScreenMaxX) {
187186
data.mouseXNow = CaptureInfo.ScreenWidth;
@@ -311,8 +310,7 @@ private void addKeyHandlers() {
311310
}
312311
});
313312

314-
data.anyPressed.addListener((obs, wasPressed, isNowPressed) ->
315-
{
313+
data.anyPressed.addListener((obs, wasPressed, isNowPressed) -> {
316314
if (isNowPressed) {
317315
yPressedAnimation.start();
318316
} else {
@@ -370,15 +368,17 @@ private void repaintCanvas() {
370368
: data.mouseYNow // UP
371369
;
372370

373-
gc.strokeRect(data.rectUpperLeftX - 1.00, data.rectUpperLeftY - 1.00, data.rectWidth + 2.00, data.rectHeight + 2.00);
371+
gc.strokeRect(data.rectUpperLeftX - 1.00, data.rectUpperLeftY - 1.00, data.rectWidth + 2.00,
372+
data.rectHeight + 2.00);
374373
gc.clearRect(data.rectUpperLeftX, data.rectUpperLeftY, data.rectWidth, data.rectHeight);
375374

376375
// draw the text
377376
if (!data.hideExtraFeatures.getValue() && (data.rectWidth > 0 || data.rectHeight > 0)) {
378377
double middle = data.rectUpperLeftX + data.rectWidth / 2.00;
379378
gc.setLineWidth(1);
380379
gc.setFill(Color.FIREBRICK);
381-
gc.fillRect(middle - 77, data.rectUpperLeftY < 50 ? data.rectUpperLeftY + 2 : data.rectUpperLeftY - 18.00, 100, 18);
380+
gc.fillRect(middle - 77, data.rectUpperLeftY < 50 ? data.rectUpperLeftY + 2 : data.rectUpperLeftY - 18.00, 100,
381+
18);
382382
gc.setFill(Color.WHITE);
383383
gc.fillText(data.rectWidth + " * " + data.rectHeight, middle - 77 + 9,
384384
data.rectUpperLeftY < 50 ? data.rectUpperLeftY + 17.00 : data.rectUpperLeftY - 4.00);
@@ -398,16 +398,16 @@ private void selectWholeScreen() {
398398

399399
public void prepareForCapture() {
400400
isSnapping = true;
401-
MainFm.stage.setOpacity(0.0f);
401+
MainForm.stage.setOpacity(0.0f);
402402
Platform.runLater(() -> {
403-
Rectangle rectangle = CommUtils.getDisplayScreen(MainFm.stage);
403+
Rectangle rectangle = CommUtils.getDisplayScreen(MainForm.stage);
404404
data.reset();
405405
CaptureInfo.ScreenMinX = rectangle.x;
406406
CaptureInfo.ScreenMaxX = rectangle.x + rectangle.width;
407407
CaptureInfo.ScreenWidth = rectangle.width;
408408
CaptureInfo.ScreenHeight = rectangle.height;
409409
BufferedImage bufferedImage = ScreenUtil.captureScreen(rectangle);
410-
//bufferedImage = Scalr.resize(bufferedImage, Scalr.Method.QUALITY, Scalr.Mode.AUTOMATIC, CaptureInfo.ScreenWidth * 2, CaptureInfo.ScreenHeight * 2);
410+
// bufferedImage = Scalr.resize(bufferedImage, Scalr.Method.QUALITY, Scalr.Mode.AUTOMATIC, CaptureInfo.ScreenWidth * 2, CaptureInfo.ScreenHeight * 2);
411411
WritableImage fxImage = SwingFXUtils.toFXImage(bufferedImage, null);
412412
deActivateAllKeys();
413413
scene.setRoot(new Pane());
@@ -417,9 +417,9 @@ public void prepareForCapture() {
417417
mainCanvas.setHeight(CaptureInfo.ScreenHeight);
418418
mainCanvas.setCursor(Cursor.CROSSHAIR);
419419
initGraphContent();
420-
rootPane.setBackground(new Background(new BackgroundImage(fxImage,
421-
BackgroundRepeat.NO_REPEAT, BackgroundRepeat.NO_REPEAT,
422-
BackgroundPosition.CENTER, new BackgroundSize(CaptureInfo.ScreenWidth, CaptureInfo.ScreenHeight, false, false, true, true))));
420+
rootPane.setBackground(new Background(new BackgroundImage(fxImage, BackgroundRepeat.NO_REPEAT,
421+
BackgroundRepeat.NO_REPEAT, BackgroundPosition.CENTER,
422+
new BackgroundSize(CaptureInfo.ScreenWidth, CaptureInfo.ScreenHeight, false, false, true, true))));
423423
repaintCanvas();
424424
stage.setScene(scene);
425425
stage.setFullScreenExitHint("");
@@ -438,19 +438,21 @@ private void prepareImage() {
438438
BufferedImage image;
439439
try {
440440
mainCanvas.setDisable(true);
441-
image = new Robot().createScreenCapture(new Rectangle(data.rectUpperLeftX + CaptureInfo.ScreenMinX, data.rectUpperLeftY + (int) CommUtils.getCrtScreen(stage).getVisualBounds().getMinY(), data.rectWidth, data.rectHeight));
441+
image = new Robot().createScreenCapture(new Rectangle(data.rectUpperLeftX + CaptureInfo.ScreenMinX,
442+
data.rectUpperLeftY + (int) CommUtils.getCrtScreen(stage).getVisualBounds().getMinY(), data.rectWidth,
443+
data.rectHeight));
442444
} catch (AWTException ex) {
443445
StaticLog.error(ex);
444446
return;
445447
} finally {
446448
mainCanvas.setDisable(false);
447-
MainFm.restore(false);
449+
MainForm.restore(false);
448450
}
449-
MainFm.doOcr(image);
451+
MainForm.doOcr(image);
450452
}
451453

452454
public void cancelSnap() {
453455
deActivateAllKeys();
454-
MainFm.restore(true);
456+
MainForm.restore(true);
455457
}
456458
}

0 commit comments

Comments
 (0)