Skip to content

Commit 9656e9e

Browse files
committed
add image recognizing animation
1 parent 0a8c092 commit 9656e9e

File tree

6 files changed

+81
-28
lines changed

6 files changed

+81
-28
lines changed

readme.md

+8-7
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77

88

99
> - 文字识别使用了各云平台开发的识别接口,因此需要联网才能正常使用;
10-
> - 本程序使用 JavaFX 开发,使用前请务必按照 **Java8** 运行环境。
10+
> - 本程序使用 JavaFX 开发,使用前请务必安装 **Java8** 运行环境。
1111
1212
## 程序使用
1313
### 启动截图
@@ -31,11 +31,12 @@
3131
![MAC权限设置](http://img.luooqi.com/Fo31NZQIhPNF6m7gOorRGDuKvaZ_)
3232

3333
## TODO
34-
- [x] 完成图片文字识别
34+
- [x] 图片文字识别
3535
- [x] 识别结果文本对齐(暂未实现多分栏)
36-
- [x] 全屏模式下截图的实现
37-
- [ ] 添加正在识别动画
38-
- [ ] 完成文本翻译功能
39-
- [ ] 完成公式识别
40-
- [ ] 完成表格识别
36+
- [x] 全屏模式下截图
37+
- [x] 添加正在识别动画
38+
- [ ] 文本翻译
39+
- [ ] 公式识别
40+
- [ ] 表格识别
41+
- [ ] 软件设置
4142

src/main/java/com/luooqi/ocr/MainFm.java

+30-3
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,14 @@
22

33
import cn.hutool.core.util.StrUtil;
44
import cn.hutool.log.StaticLog;
5+
import com.luooqi.ocr.controller.ProcessController;
56
import com.luooqi.ocr.model.StageInfo;
67
import com.luooqi.ocr.snap.ScreenCapture;
78
import com.luooqi.ocr.utils.CommUtils;
89
import com.luooqi.ocr.utils.GlobalKeyListener;
10+
import com.luooqi.ocr.utils.OcrUtils;
911
import javafx.application.Application;
12+
import javafx.application.Platform;
1013
import javafx.beans.property.SimpleStringProperty;
1114
import javafx.geometry.Insets;
1215
import javafx.scene.Scene;
@@ -22,6 +25,7 @@
2225
import org.jnativehook.GlobalScreen;
2326

2427
import javax.swing.*;
28+
import java.awt.image.BufferedImage;
2529
import java.lang.reflect.Method;
2630
import java.net.URL;
2731
import java.util.HashMap;
@@ -41,15 +45,16 @@ public static void main(String[] args) {
4145
public static Stage stage;
4246
private static Scene mainScene;
4347
private static ScreenCapture screenCapture;
48+
private static ProcessController processController;
4449
public static TextArea textArea;
4550
//private static boolean isSegment = true;
4651
//private static String ocrText = "";
47-
//private static BooleanProperty isOcr = new SimpleBooleanProperty(false);
4852

4953
@Override
5054
public void start(Stage primaryStage) {
5155
stage = primaryStage;
5256
screenCapture = new ScreenCapture(stage);
57+
processController = new ProcessController();
5358
initKeyHook();
5459

5560
// ToggleGroup segmentGrp = new ToggleGroup();
@@ -77,6 +82,8 @@ public void start(Stage primaryStage) {
7782
topBar.setPadding(new Insets(6, 8, 6, 8));
7883

7984
textArea = new TextArea();
85+
textArea.setId("ocrTextArea");
86+
textArea.setWrapText(false);
8087
textArea.setFont(Font.font("Arial", FontPosture.REGULAR, 14));
8188

8289
ToolBar footerBar = new ToolBar();
@@ -182,15 +189,35 @@ public static void cancelSnap() {
182189
// textArea.setText(ocrText);
183190
// }
184191

185-
public static void restore() {
192+
public static void doOcr(BufferedImage image){
193+
processController.show();
194+
Thread ocrThread = new Thread(()->{
195+
byte[] bytes = CommUtils.imageToBytes(image);
196+
String text = OcrUtils.sogouWebOcr(bytes);
197+
Platform.runLater(()-> {
198+
processController.close();
199+
stage.show();
200+
textArea.setText(text);
201+
});
202+
});
203+
ocrThread.setDaemon(false);
204+
ocrThread.start();
205+
}
206+
207+
public static void restore(boolean focus) {
186208
stage.setAlwaysOnTop(false);
187209
stage.setScene(mainScene);
188210
stage.setFullScreen(stageInfo.isFullScreenState());
189211
stage.setX(stageInfo.getX());
190212
stage.setY(stageInfo.getY());
191213
stage.setWidth(stageInfo.getWidth());
192214
stage.setHeight(stageInfo.getHeight());
193-
stage.requestFocus();
215+
if (focus){
216+
stage.requestFocus();
217+
}
218+
else{
219+
stage.close();
220+
}
194221
}
195222

196223
private static void initKeyHook(){
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
package com.luooqi.ocr.controller;
2+
3+
import com.luooqi.ocr.utils.CommUtils;
4+
import javafx.scene.Scene;
5+
import javafx.scene.control.ProgressIndicator;
6+
import javafx.stage.Stage;
7+
import javafx.stage.StageStyle;
8+
9+
public class ProcessController extends Stage {
10+
11+
public ProcessController(){
12+
ProgressIndicator progressIndicator = new ProgressIndicator();
13+
progressIndicator.setStyle(CommUtils.STYLE_TRANSPARENT);
14+
int circleSize = 100;
15+
progressIndicator.setMaxWidth(circleSize);
16+
progressIndicator.setMaxHeight(circleSize);
17+
progressIndicator.setAccessibleText("正在识别...");
18+
Scene scene = new Scene(progressIndicator, circleSize, circleSize);
19+
setScene(scene);
20+
initStyle(StageStyle.TRANSPARENT);
21+
}
22+
}

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

+3-9
Original file line numberDiff line numberDiff line change
@@ -405,20 +405,14 @@ private void prepareImage() {
405405
return;
406406
} finally {
407407
mainCanvas.setDisable(false);
408-
MainFm.restore();
408+
MainFm.restore(false);
409409
}
410-
Thread ocrThread = new Thread(()->{
411-
byte[] bytes = CommUtils.imageToBytes(image);
412-
String text = OcrUtils.sogouWebOcr(bytes);
413-
Platform.runLater(()-> MainFm.textArea.setText(text));
414-
});
415-
ocrThread.setDaemon(false);
416-
ocrThread.start();
410+
MainFm.doOcr(image);
417411
}
418412

419413
public void cancelSnap(){
420414
deActivateAllKeys();
421-
MainFm.restore();
415+
MainFm.restore(true);
422416
}
423417

424418
private int[] getRectangleBounds() {

src/main/java/com/luooqi/ocr/utils/CommUtils.java

+13-8
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ public class CommUtils {
3535
public static final int BUTTON_SIZE = 28;
3636
public static Background BG_TRANSPARENT = new Background(new BackgroundFill(Color.TRANSPARENT,
3737
CornerRadii.EMPTY, Insets.EMPTY));
38-
private static Pattern NORMAL_CHAR = Pattern.compile("[\\u4e00-\\u9fa5\\w、-]");
38+
private static Pattern NORMAL_CHAR = Pattern.compile("[\\u4e00-\\u9fa5\\w、-]");
3939
public static Separator SEPARATOR = new Separator(Orientation.VERTICAL);
4040
private static final float IMAGE_QUALITY = 0.5f;
4141
private static final int SAME_LINE_LIMIT = 8;
@@ -106,21 +106,26 @@ static String combineTextBlocks(List<TextBlock> textBlocks) {
106106
if (lastBlock != null) {
107107
String blockTxt = lastBlock.getText().trim();
108108
String endTxt = blockTxt.substring(blockTxt.length() - 1);
109-
if (maxX - lastBlock.getTopRight().x >= CHAR_WIDTH ||
110-
(!NORMAL_CHAR.matcher(endTxt).find() &&
111-
(firstBlock.getTopLeft().x - minX) >= CHAR_WIDTH)) {
109+
if (maxX - lastBlock.getTopRight().x >= CHAR_WIDTH * 2 ||
110+
!NORMAL_CHAR.matcher(endTxt).find() ||
111+
(NORMAL_CHAR.matcher(endTxt).find() &&
112+
(firstBlock.getTopLeft().x - minX) > CHAR_WIDTH * 2)){
112113
sb.append("\n");
113114
for (int i = 0, ln = (firstBlock.getTopLeft().x - minX) / CHAR_WIDTH; i < ln; i++) {
114115
sb.append(" ");
115116
}
116117
}
117118
}
118-
for (TextBlock text : line) {
119+
for (int i = 0; i < line.size(); i++) {
120+
TextBlock text = line.get(i);
119121
String ocrText = text.getText();
120-
sb.append(ocrText);
121-
if (ocrText.matches("^\\w+$")) {
122-
sb.append(" ");
122+
if (i > 0) {
123+
for (int a = 0, ln = (text.getTopLeft().x - line.get(i - 1).getTopRight().x) / CHAR_WIDTH;
124+
a < ln; a++) {
125+
sb.append(" ");
126+
}
123127
}
128+
sb.append(ocrText);
124129
}
125130
lastBlock = line.get(line.size() - 1);
126131
}

src/main/resources/css/main.css

+5-1
Original file line numberDiff line numberDiff line change
@@ -37,4 +37,8 @@
3737

3838
/*#topBar .separator{*/
3939
/*-fx-padding: 2px -5px 2px -2px;*/
40-
/*}*/
40+
/*}*/
41+
42+
#ocrTextArea{
43+
-fx-text-fill: #343434;
44+
}

0 commit comments

Comments
 (0)