亲宝软件园·资讯

展开

java程序员自己的图片转文字OCR识图工具分享

思想永无止境 人气:2

图片转文字OCR识图工具

图片文字识别,只支持在windows上运行,语言自动识别,调用的是百度OCR-API,需要提供百度智能云管理后台的应用的API Key和Secret Key。

打包成jar文件放桌面可以自己用也可以给亲人朋友用。

只需三个文件

即可自己开发一个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上运行,语言自动识别,调用的是百度OCR-API,需要提供百度智能云管理后台的应用的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");// 设置滚动条样式为window风格的滚动条样式
        // 设置文件夹在swing中所显示的图标
        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应用密钥.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,调用的是百度OCR-API,需要提供百度智能云管理后台的应用的API Key和Secret Key。\r\n" +
                "\t1.1,进入百度智能云服务列表:https://console.bce.baidu.com/ai/#/ai/ocr/overview/index 。\r\n" +
                "\t1.2,点击'通用场景OCR',然后找到'通用文字识别(高精度版)'后点击开通。\r\n" +
                "\t1.3,进入创建应用页面:https://console.bce.baidu.com/ai/#/ai/ocr/app/create。\r\n" +
                "\t1.4,填写应用名称,应用归属选择'个人',随便填写应用描述,然后点击'立即创建'。\r\n" +
                "\t1.5,进入应用列表页面:https://console.bce.baidu.com/ai/#/ai/ocr/app/list。\r\n" +
                "\t1.6,复制出API Key和Secret Key。\r\n" +
                "\t1.7,该接口每天只能免费调用500次,超出部分百度要收费。\r\n" +
                "2,语言可以自动识别。\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("请先调用接口,成功后才能保存密钥!");
                    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("转化文字失败!");
                } 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;// 获取凭证时的时间,单位:毫秒数,System.currentTimeMillis
    private static volatile int expireTime;// 凭证有效时间,单位:秒

    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", "空的调用结果");
            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", "未解析到结果");
                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", "无法解析调用结果");
        }
        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", "系统错误,请稍后重试");
                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", "系统错误,请稍后重试");
            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>

以上为个人经验,希望能给大家一个参考,也希望大家多多支持。

加载全部内容

相关教程
猜你喜欢
用户评论