java程序員自己的圖片轉(zhuǎn)文字OCR識圖工具分享
圖片轉(zhuǎn)文字OCR識圖工具
圖片文字識別,只支持在windows上運(yùn)行,語言自動(dòng)識別,調(diào)用的是百度OCR-API,需要提供百度智能云管理后臺的應(yīng)用的API Key和Secret Key。
打包成jar文件放桌面可以自己用也可以給親人朋友用。
只需三個(gè)文件
即可自己開發(fā)一個(gè)OCR工具軟件:
App.java
package translate.image;
import javax.swing.*;
import javax.swing.border.EmptyBorder;
import javax.swing.filechooser.FileFilter;
import javax.swing.filechooser.FileSystemView;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.File;
import java.io.IOException;
import java.nio.charset.Charset;
import java.nio.file.Files;
import java.nio.file.StandardOpenOption;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
/**
* 圖片文字識別,只支持在windows上運(yùn)行,語言自動(dòng)識別,調(diào)用的是百度OCR-API,需要提供百度智能云管理后臺的應(yīng)用的API Key和Secret Key
*
* @author tang
*/
public class App {
public static void main(String[] args) throws Exception {
UIManager.setLookAndFeel(com.sun.java.swing.plaf.windows.WindowsLookAndFeel.class.getName());
UIManager.put("ScrollBarUI", "com.sun.java.swing.plaf.windows.WindowsScrollBarUI");// 設(shè)置滾動(dòng)條樣式為window風(fēng)格的滾動(dòng)條樣式
// 設(shè)置文件夾在swing中所顯示的圖標(biāo)
UIManager.put("FileView.directoryIcon", FileSystemView.getFileSystemView().getSystemIcon(new File(System.getProperty("user.dir"))));
String oldApiKey = "";
String oldSecretKey = "";
final File keyFile = new File(System.getProperty("user.dir") + "/百度OCR應(yīng)用密鑰.txt");
if (keyFile.exists()) {
try {
List<String> keyTextList = Files.readAllLines(keyFile.toPath());
if (keyTextList != null && keyTextList.size() >= 2) {
oldApiKey = keyTextList.get(0);
oldSecretKey = keyTextList.get(1);
}
} catch (Exception e) {
e.printStackTrace();
}
}
final JFrame jFrame = new JFrame();
JPanel contentPane = new JPanel();
jFrame.setContentPane(contentPane);
contentPane.setBorder(new EmptyBorder(10, 10, 10, 10));
contentPane.setLayout(new FlowLayout(FlowLayout.CENTER, 0, 20));
JPanel jp1 = new JPanel();
jp1.setLayout(new FlowLayout(FlowLayout.LEFT, 0, 0));
jp1.setBorder(new EmptyBorder(0, 0, 0, 0));
jp1.setPreferredSize(new Dimension(400, 30));
JLabel apiKeyLabel = new JLabel(" API Key : ");
jp1.add(apiKeyLabel);
final JTextField apiKeyTextField = new JTextField("", 40);
apiKeyTextField.setText(oldApiKey);
jp1.add(apiKeyTextField);
contentPane.add(jp1);
JPanel jp2 = new JPanel();
jp2.setLayout(new FlowLayout(FlowLayout.LEFT, 0, 0));
jp2.setBorder(new EmptyBorder(0, 0, 0, 0));
jp2.setPreferredSize(new Dimension(400, 30));
JLabel secretKeyLabel = new JLabel("Secret Key : ");
jp2.add(secretKeyLabel);
final JTextField secretKeyTextField = new JTextField("", 40);
secretKeyTextField.setText(oldSecretKey);
jp2.add(secretKeyTextField);
contentPane.add(jp2);
JPanel jp3 = new JPanel();
jp3.setLayout(new FlowLayout(FlowLayout.LEFT, 0, 0));
jp3.setBorder(new EmptyBorder(0, 0, 0, 0));
jp2.setPreferredSize(new Dimension(400, 30));
JLabel imageLabel = new JLabel(" Image : ");
jp3.add(imageLabel);
final JTextField imageTextField = new JTextField("", 40);
jp3.add(imageTextField);
JButton selFileBtn = new JButton("...");
jp3.add(selFileBtn);
final JFileChooser chooser = new JFileChooser();
chooser.setCurrentDirectory(new File(System.getProperty("user.home") + "/Desktop"));
chooser.setFileFilter(new FileFilter() {
public boolean accept(File f) {
if (f.isDirectory()) {
return true;
}
if (f.getName().endsWith(".png") || f.getName().endsWith(".jpg") || f.getName().endsWith(".jpeg") || f.getName().endsWith(".bmp")) {
return true;
}
return false;
}
public String getDescription() {
return "png/jpg/bmp";
}
});
selFileBtn.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
int i = chooser.showOpenDialog(jFrame);
if (JFileChooser.APPROVE_OPTION == i) {
File selectedFile = chooser.getSelectedFile();
if (selectedFile != null && selectedFile.getAbsolutePath() != null) {
imageTextField.setText(selectedFile.getAbsolutePath());
return;
}
}
imageTextField.setText("");
}
});
contentPane.add(jp3);
JPanel jp4 = new JPanel();
jp4.setLayout(new FlowLayout(FlowLayout.RIGHT, 0, 0));
jp4.setBorder(new EmptyBorder(0, 0, 0, 0));
jp4.setPreferredSize(new Dimension(400, 30));
JButton saveKeyBtn = new JButton("保存密鑰");
jp4.add(saveKeyBtn);
contentPane.add(jp4);
JButton okBtn = new JButton("識別文字");
jp4.add(okBtn);
JPanel jp5 = new JPanel();
jp5.setLayout(new FlowLayout(FlowLayout.LEFT, 0, 0));
jp5.setBorder(new EmptyBorder(0, 0, 0, 0));
jp5.setPreferredSize(new Dimension(400, 500));
final JTextArea textArea = new JTextArea(30, 40);
textArea.setSize(new Dimension(380, 500));
textArea.setText("1,調(diào)用的是百度OCR-API,需要提供百度智能云管理后臺的應(yīng)用的API Key和Secret Key。\r\n" +
"\t1.1,進(jìn)入百度智能云服務(wù)列表:https://console.bce.baidu.com/ai/#/ai/ocr/overview/index 。\r\n" +
"\t1.2,點(diǎn)擊'通用場景OCR',然后找到'通用文字識別(高精度版)'后點(diǎn)擊開通。\r\n" +
"\t1.3,進(jìn)入創(chuàng)建應(yīng)用頁面:https://console.bce.baidu.com/ai/#/ai/ocr/app/create。\r\n" +
"\t1.4,填寫應(yīng)用名稱,應(yīng)用歸屬選擇'個(gè)人',隨便填寫應(yīng)用描述,然后點(diǎn)擊'立即創(chuàng)建'。\r\n" +
"\t1.5,進(jìn)入應(yīng)用列表頁面:https://console.bce.baidu.com/ai/#/ai/ocr/app/list。\r\n" +
"\t1.6,復(fù)制出API Key和Secret Key。\r\n" +
"\t1.7,該接口每天只能免費(fèi)調(diào)用500次,超出部分百度要收費(fèi)。\r\n" +
"2,語言可以自動(dòng)識別。\r\n" +
"3,只支持png/jpg/bmp格式圖片。");
textArea.setWrapStyleWord(true);
textArea.setAutoscrolls(true);
textArea.setLineWrap(true);
JScrollPane jsp = new JScrollPane(textArea);
jsp.setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_NEVER);
jsp.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED);
jp5.add(jsp);
contentPane.add(jp5);
saveKeyBtn.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
if (BaiduCloudApiUtil.appApiKey.trim().isEmpty() || BaiduCloudApiUtil.appSecretKey.trim().isEmpty()) {
textArea.setText("請先調(diào)用接口,成功后才能保存密鑰!");
return;
}
List<String> list = new ArrayList<>(2);
list.add(BaiduCloudApiUtil.appApiKey);
list.add(BaiduCloudApiUtil.appSecretKey);
try {
Files.write(keyFile.toPath(), list, Charset.forName("UTF-8"), StandardOpenOption.CREATE);
textArea.setText("保存密鑰成功!");
} catch (IOException ex) {
ex.printStackTrace();
}
}
});
okBtn.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
if (apiKeyTextField.getText().trim().isEmpty()) {
textArea.setText("請輸入API Key!");
return;
}
if (secretKeyTextField.getText().trim().isEmpty()) {
textArea.setText("請輸入Secret Key!");
return;
}
BaiduCloudApiUtil.appApiKey = apiKeyTextField.getText().trim();
BaiduCloudApiUtil.appSecretKey = secretKeyTextField.getText().trim();
if (!"".equals(imageTextField.getText().trim())) {
try {
byte[] bytes = Files.readAllBytes(chooser.getSelectedFile().toPath());
Map<String, Object> map = BaiduCloudApiUtil.queryOcrResult(bytes);
if (map != null && !map.isEmpty()) {
Boolean success = (Boolean) map.get("success");
if (success) {
String data = (String) map.get("data");
if (data != null && !data.trim().isEmpty()) {
textArea.setText(data);
} else {
textArea.setText("");
}
} else {
String message = (String) map.get("message");
textArea.setText(message);
}
return;
}
} catch (Exception ex) {
ex.printStackTrace();
}
textArea.setText("轉(zhuǎn)化文字失??!");
} else {
textArea.setText("沒有選擇文件!");
}
}
});
jFrame.setSize(500, 800);
jFrame.setLocationRelativeTo(null);
jFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
jFrame.setVisible(true);
}
}BaiduCloudApiUtil.java
package translate.image;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import java.io.BufferedReader;
import java.io.File;
import java.io.InputStreamReader;
import java.lang.reflect.Method;
import java.net.HttpURLConnection;
import java.net.URL;
import java.net.URLEncoder;
import java.nio.file.Files;
import java.util.HashMap;
import java.util.Map;
public class BaiduCloudApiUtil {
static String appApiKey = "";
static String appSecretKey = "";
private static volatile String accessToken;
private static volatile long accessTokenTime;// 獲取憑證時(shí)的時(shí)間,單位:毫秒數(shù),System.currentTimeMillis
private static volatile int expireTime;// 憑證有效時(shí)間,單位:秒
private static void clearToken() {
accessToken = "";
expireTime = 0;
accessTokenTime = 0;
}
public static String getAccessToken() {
if (!(accessToken == null || accessToken.trim().isEmpty()) && accessTokenTime > 0 && expireTime > 0) {
long extime = accessTokenTime + (expireTime * 1000);
long nowTime = System.currentTimeMillis();
if (extime - nowTime > 1000) {// 仍然有效
return accessToken;
}
}
String authHost = "https://aip.baidubce.com/oauth/2.0/token?";
String getAccessTokenUrl = authHost + "grant_type=client_credentials" + "&client_id=" + appApiKey + "&client_secret=" + appSecretKey;
try {
URL realUrl = new URL(getAccessTokenUrl);
HttpURLConnection connection = (HttpURLConnection) realUrl.openConnection();
connection.setRequestMethod("GET");
connection.connect();
try (BufferedReader in = new BufferedReader(new InputStreamReader(connection.getInputStream()))) {
String result = "";
String line;
while ((line = in.readLine()) != null) {
result += line;
}
JSONObject jsonObject = (JSONObject) JSONObject.parse(result);
expireTime = jsonObject.getInteger("expires_in");
accessToken = jsonObject.getString("access_token");
accessTokenTime = System.currentTimeMillis();
} catch (Throwable e) {
e.printStackTrace();
clearToken();
}
} catch (Throwable e) {
e.printStackTrace();
clearToken();
}
return accessToken;
}
public static Map<String, Object> parse(JSONObject jsonObject) {
HashMap<String, Object> map = new HashMap<>();
map.put("success", false);
if (jsonObject == null) {
map.put("message", "空的調(diào)用結(jié)果");
return map;
}
try {
Integer words_result_num = jsonObject.getInteger("words_result_num");
if (words_result_num == null || words_result_num.intValue() <= 0) {
map.put("message", "未解析到結(jié)果");
return map;
}
JSONArray words_result = jsonObject.getJSONArray("words_result");
StringBuffer sb = new StringBuffer();
for (Object obj : words_result) {
JSONObject jo = (JSONObject) obj;
String words = jo.getString("words");
sb.append(words + "\r\n");
}
System.out.println(sb);
map.put("data", sb.toString());
map.put("success", true);
} catch (Exception e) {
map.put("message", "無法解析調(diào)用結(jié)果");
}
return map;
}
public static JSONObject ocr(String httpUrl, String httpArg) {
try {
URL url = new URL(httpUrl);
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
connection.setRequestMethod("POST");
connection.setRequestProperty("Content-Type", "application/x-www-form-urlencoded");
connection.setRequestProperty("apikey", appApiKey);
connection.setDoOutput(true);
connection.getOutputStream().write(httpArg.getBytes("UTF-8"));
connection.connect();
try (BufferedReader reader = new BufferedReader(new InputStreamReader(connection.getInputStream(), "UTF-8"))) {
StringBuffer sbf = new StringBuffer();
String strRead = null;
while ((strRead = reader.readLine()) != null) {
sbf.append(strRead);
sbf.append("\r\n");
}
String result = sbf.toString();
JSONObject jsonObject = (JSONObject) JSONObject.parse(result);
return jsonObject;
} catch (Throwable e) {
e.printStackTrace();
}
} catch (Throwable e) {
e.printStackTrace();
}
return null;
}
public static String encodeBase64(byte[] input) throws Exception {
Class<?> clazz = Class.forName("com.sun.org.apache.xerces.internal.impl.dv.util.Base64");
Method mainMethod = clazz.getMethod("encode", byte[].class);
mainMethod.setAccessible(true);
Object retObj = mainMethod.invoke(null, new Object[]{input});
return (String) retObj;
}
public static Map<String, Object> queryOcrResult(byte[] fileBytes) {
try {
String imageBase = encodeBase64(fileBytes);
imageBase = URLEncoder.encode(imageBase, "UTF-8");
String httpUrl = "https://aip.baidubce.com/rest/2.0/ocr/v1/accurate_basic?access_token=" + getAccessToken();
String httpArg = "language_type=auto_detect&image=" + imageBase;
JSONObject jsonObject = ocr(httpUrl, httpArg);
if (jsonObject == null) {
HashMap<String, Object> map = new HashMap<>();
map.put("success", false);
map.put("message", "系統(tǒng)錯(cuò)誤,請稍后重試");
return map;
}
Map<String, Object> map = parse(jsonObject);
return map;
} catch (Exception e) {
HashMap<String, Object> map = new HashMap<>();
map.put("success", false);
map.put("message", "系統(tǒng)錯(cuò)誤,請稍后重試");
return map;
}
}
public static void main(String[] args) throws Exception {
File file = new File("C:\\Users\\tang8\\Desktop\\2022-07-21_070822.png");
byte[] data = Files.readAllBytes(file.toPath());
Map<String, Object> map = queryOcrResult(data);
System.out.println(map.get("data"));
}
}pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>translate.image</groupId>
<artifactId>TranslateImage</artifactId>
<version>1.0-SNAPSHOT</version>
<name>TranslateImage</name>
<url>http://www.example.com</url>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<maven.compiler.source>1.8</maven.compiler.source>
<maven.compiler.target>1.8</maven.compiler.target>
</properties>
<dependencies>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.29</version>
</dependency>
</dependencies>
<build>
<pluginManagement>
<plugins>
<plugin>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.8.0</version>
</plugin>
<plugin>
<artifactId>maven-jar-plugin</artifactId>
<version>3.0.2</version>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
<version>3.1.1</version>
</plugin>
</plugins>
</pluginManagement>
<plugins>
<plugin>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>8</source>
<target>8</target>
</configuration>
</plugin>
<plugin>
<artifactId>maven-jar-plugin</artifactId>
<configuration>
<archive>
<manifest>
<mainClass>translate.image.App</mainClass>
</manifest>
</archive>
</configuration>
</plugin>
<plugin>
<artifactId>maven-shade-plugin</artifactId>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>shade</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。
- java實(shí)現(xiàn)圖片文字識別ocr
- java實(shí)現(xiàn)百度云OCR文字識別 高精度OCR識別身份證信息
- Java使用OCR技術(shù)識別驗(yàn)證碼實(shí)現(xiàn)自動(dòng)化登陸方法
- Java OCR tesseract 圖像智能文字字符識別技術(shù)實(shí)例代碼
- Java使用Tesseract-Ocr識別數(shù)字
- Java使用Tessdata做OCR圖片文字識別的詳細(xì)思路
- java實(shí)現(xiàn)騰訊ocr圖片識別接口調(diào)用
- 不到十行實(shí)現(xiàn)javaCV圖片OCR文字識別
- Windows下Java調(diào)用OCR進(jìn)行圖片識別
- 用Java實(shí)現(xiàn)OCR功能揭秘
相關(guān)文章
SpringBoot集成MybatisPlus報(bào)錯(cuò)的解決方案
這篇文章主要介紹了SpringBoot集成MybatisPlus報(bào)錯(cuò)的解決方案,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2019-12-12
spring webflux自定義netty 參數(shù)解析
這篇文章主要介紹了spring webflux自定義netty 參數(shù)解析,具有很好的參考價(jià)值,希望對大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2021-09-09
如何讀取properties或yml文件數(shù)據(jù)并匹配
這篇文章主要介紹了如何讀取properties或yml文件數(shù)據(jù)并匹配方式,具有很好的參考價(jià)值,希望對大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2021-12-12
Maven中dependencyManagement管理項(xiàng)目依賴項(xiàng)
在開發(fā)?Java?項(xiàng)目時(shí),管理和協(xié)調(diào)依賴項(xiàng)的版本號是一項(xiàng)重要而繁瑣的任務(wù),本文主要介紹了Maven中dependencyManagement管理項(xiàng)目依賴項(xiàng),具有一定的參考價(jià)值,感興趣的可以了解一下2024-01-01
springboot集成kafka消費(fèi)手動(dòng)啟動(dòng)停止操作
這篇文章主要介紹了springboot集成kafka消費(fèi)手動(dòng)啟動(dòng)停止操作,本文給大家介紹項(xiàng)目場景及解決分析,結(jié)合實(shí)例代碼給大家介紹的非常詳細(xì),需要的朋友可以參考下2022-09-09
Springbootadmin與security沖突問題及解決
這篇文章主要介紹了Springbootadmin與security沖突問題及解決方案,具有很好的參考價(jià)值,希望對大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2024-08-08

