文字提取(Java+Tesseract_OCR)

文字提取Java+Tesseract_OCR

开发环境

系统: windows 11
jdk: 1.8
框架: spring boot 2.1.4 + maven
工具: idea

Tesseract 安装

相关链接

官方网站:https://github.com/tesseract-ocr/tesseract
官方文档:https://github.com/tesseract-ocr/tessdoc
语言包地址:https://github.com/tesseract-ocr/tessdata
下载地址:https://digi.bib.uni-mannheim.de/tesseract/
在我的资源里面也提交了5.0 windows 的安装包.(我想免费的,官方没有这个选择)
64位: https://download.csdn.net/download/qq_35885175/68236012
32位: https://download.csdn.net/download/qq_35885175/68235937

安装

  1. 双击 选择语言点击OK
    文字提取(Java+Tesseract_OCR)

  2. 直接next(下一步)
    文字提取(Java+Tesseract_OCR)

  3. 日常同意协议
    文字提取(Java+Tesseract_OCR)

  4. 选择给谁安装(看自己需要,我的是个人电脑)
    文字提取(Java+Tesseract_OCR)

  5. 接下来是选择语言包
    最后那两个框就是下载语言包的不建议选择(很慢,除非*,下面会有教程扩展语言包的)
    文字提取(Java+Tesseract_OCR)

  6. 选择安装目录
    文字提取(Java+Tesseract_OCR)

  7. next,等待安装完成
    (有一个选择是否添加注册表的,我忘记截图了,默认next 干就完了)
    文字提取(Java+Tesseract_OCR)

  8. 安装完成(结束)
    文字提取(Java+Tesseract_OCR)

配置环境变量

这个步骤对于大家来说就很简单了

  1. 电脑设置(高级环境变量)
    windows11
    文字提取(Java+Tesseract_OCR)
    windows 10(windows server 凑合看吧)
    文字提取(Java+Tesseract_OCR)
  2. 点击环境变量
    文字提取(Java+Tesseract_OCR)
  3. 系统变量中找到PATH
    (用户变量也可,不能用 别找我)
    文字提取(Java+Tesseract_OCR)
  4. 点击新建,选择路径
    文字提取(Java+Tesseract_OCR)
  5. 大概就是这个样,点击确定就行了
    文字提取(Java+Tesseract_OCR)

检查时候安装成功

万能的cmd来了

  1. win+R 输入cmd
    文字提取(Java+Tesseract_OCR)
  2. 小黑框输入 tesseract -v文字提取(Java+Tesseract_OCR)
  3. 看到了吗,我们安装的版本
    文字提取(Java+Tesseract_OCR)

扩展语言包

上面那个链接可以跳转github里面下载(传送门)
csdn我上传的:https://download.csdn.net/download/qq_35885175/68245426
这个东西就是简体中文的啦
文字提取(Java+Tesseract_OCR)
go:
把下载好的文件放入安装目录中,就完成了
文字提取(Java+Tesseract_OCR)
测试时候扩展是否成功
小黑框(cmd) 输入: tesseract --list-langs
文字提取(Java+Tesseract_OCR)
搞定

Java代码(上小菜)

1.POM文件

 <dependency>
            <groupId>net.sourceforge.tess4j</groupId>
            <artifactId>tess4j</artifactId>
            <version>5.0.0</version>
 </dependency>

下载不成功的话 多切换几个 version
jar包链接 : https://download.csdn.net/download/qq_35885175/68256292
或者下载 这个我上传的 直接按照目录扔到仓库

2.ImageIOHelper代码

package com.lk.integutils.utils;

import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.util.Iterator;
import java.util.Locale;

import javax.imageio.IIOImage;
import javax.imageio.ImageIO;
import javax.imageio.ImageReader;
import javax.imageio.ImageWriteParam;
import javax.imageio.ImageWriter;
import javax.imageio.metadata.IIOMetadata;
import javax.imageio.stream.ImageInputStream;
import javax.imageio.stream.ImageOutputStream;

import com.github.jaiimageio.plugins.tiff.TIFFImageWriteParam;

public class ImageIOHelper {

    //设置语言
    private Locale locale=Locale.CHINESE;

    //自定义语言构造的方法
    public ImageIOHelper(Locale locale){
        this.locale=locale;
    }
    //默认构造器Locale.CHINESE

    public ImageIOHelper(){
    }


    /**
     * 创建临时图片文件防止损坏初始文件
     * @param imageFile
     * @param imageFormat like png,jps .etc
     * @return TempFile of Image
     */
    public File createImage(File imageFile, String imageFormat) throws IOException {

        //读取图片文件
        Iterator<ImageReader> readers = ImageIO.getImageReadersByFormatName(imageFormat);
        ImageReader reader = readers.next();
        //获取文件流
        ImageInputStream iis = ImageIO.createImageInputStream(imageFile);
        reader.setInput(iis);
        IIOMetadata streamMetadata = reader.getStreamMetadata();

        //设置writeParam
        TIFFImageWriteParam tiffWriteParam = new TIFFImageWriteParam(Locale.CHINESE);
        tiffWriteParam.setCompressionMode(ImageWriteParam.MODE_DISABLED);
        //设置可否压缩

        //获得tiffWriter和设置output
        Iterator<ImageWriter> writers = ImageIO.getImageWritersByFormatName("tiff");
        ImageWriter writer = writers.next();


        BufferedImage bi = reader.read(0);
        IIOImage image = new IIOImage(bi,null,reader.getImageMetadata(0));
        File tempFile = tempImageFile(imageFile);
        ImageOutputStream ios = ImageIO.createImageOutputStream(tempFile);

        writer.setOutput(ios);
        writer.write(streamMetadata, image, tiffWriteParam);

        ios.close();
        iis.close();
        writer.dispose();
        reader.dispose();

        return tempFile;
    }

    /**
     * 给tempfile添加后缀
     * @param imageFile
     * @throws IOException
     */
    private File tempImageFile(File imageFile) throws IOException {
        String path = imageFile.getPath();
        StringBuffer strB = new StringBuffer(path);
        strB.insert(path.lastIndexOf('.'),"_text_recognize_temp");
        String s=strB.toString().replaceFirst("(?<=//.)(//w+)$", "tif");
        //设置文件隐藏
        Runtime.getRuntime().exec("attrib "+"\""+s+"\""+" +H");
        return new File(strB.toString());
    }

}

3. OCRUtil代码

package com.lk.integutils.utils;

import java.io.*;
import java.util.ArrayList;
import java.util.List;
import java.util.Locale;

import org.jdesktop.swingx.util.OS;

public class OCRUtil  {
    private final String LANG_OPTION = "-l";
    //英文字母小写l,并非阿拉伯数字1

    private final String EOL = System.getProperty("line.separator");

    /**
     * ocr的安装路径
     */
    private String tessPath =  "D:\\Utils\\Tesseract-OCR";



    public OCRUtil(String tessPath,String transFileName){
        this.tessPath=tessPath;
    }

    //OCRUtil的构造方法,默认路径是"C://Program Files (x86)//Tesseract-OCR"

    public OCRUtil(){     }

    public String getTessPath() {
        return tessPath;
    }
    public void setTessPath(String tessPath) {
        this.tessPath = tessPath;
    }
    public String getLANG_OPTION() {
        return LANG_OPTION;
    }
    public String getEOL() {
        return EOL;
    }


    /**
     * @return 识别后的文字
     */
    public String recognizeText(File imageFile,String imageFormat)throws Exception{
        File tempImage = new ImageIOHelper().createImage(imageFile,imageFormat);
        return ocrImages(tempImage, imageFile);
    }

    /**
     *  可以自定义语言
     */
    public String recognizeText(File imageFile,String imageFormat,Locale locale)throws Exception{
        File tempImage = new ImageIOHelper(locale).createImage(imageFile,imageFormat);
        return ocrImages(tempImage, imageFile);
    }

    /**
     * @param
     * @param
     * @return 识别后的内容
     * @throws IOException
     * @throws InterruptedException
     */
    private String ocrImages(File tempImage,File imageFile) throws IOException, InterruptedException{

        //设置输出文件的保存的文件目录,以及文件名
        File outputFile = new File(imageFile.getParentFile(),"test");
        StringBuffer strB = new StringBuffer();


        //设置命令行内容
        List<String> cmd = new ArrayList<String>();
        if(OS.isWindowsXP()){
            cmd.add(tessPath+"//tesseract");
        }else if(OS.isLinux()){
            cmd.add("tesseract");
        }else{
            cmd.add(tessPath+"//tesseract");
        }
        cmd.add("");
        cmd.add(outputFile.getName());
        cmd.add(LANG_OPTION);
        //中文包
        cmd.add("chi_sim");
        //常用数学公式包
        cmd.add("equ");
        //英语包
        cmd.add("eng");


        //创建操作系统进程
        ProcessBuilder pb = new ProcessBuilder();
        //设置此进程生成器的工作目录
        pb.directory(imageFile.getParentFile());
        cmd.set(1, tempImage.getName());
        //设置要执行的cmd命令
        pb.command(cmd);
        //设置后续子进程生成的错误输出都将与标准输出合并
        pb.redirectErrorStream(true);

        long startTime = System.currentTimeMillis();
        System.out.println("开始时间:" + startTime);
        //开始执行,并返回进程实例
        Process process = pb.start();
        //最终执行命令为:tesseract 1.png test -l chi_sim+equ+eng
        // 输入输出流优化
//        printMessage(process.getInputStream());
//        printMessage(process.getErrorStream());
        int w = process.waitFor();
        //删除临时正在工作文件
        tempImage.delete();
        if(w==0){
            // 0代表正常退出
            BufferedReader in = new BufferedReader(new InputStreamReader(new FileInputStream(outputFile.getAbsolutePath()+".txt"),"UTF-8"));
            String str;
            while((str = in.readLine())!=null){
                strB.append(str).append(EOL);
            }
            in.close();

            long endTime = System.currentTimeMillis();
            System.out.println("结束时间:" + endTime);
            System.out.println("耗时:" + (endTime - startTime) + "毫秒");

        }else{
            String msg;
            switch(w){
                case 1:
                    msg = "Errors accessing files.There may be spaces in your image's filename.";
                    break;
                case 29:
                    msg = "Cannot recongnize the image or its selected region.";
                    break;
                case 31:
                    msg = "Unsupported image format.";
                    break;
                default:
                    msg = "Errors occurred.";
            }
            tempImage.delete();
            throw new RuntimeException(msg);
        }
        // 删除提取到文字的临时文件
        new File(outputFile.getAbsolutePath()+".txt").delete();
        return strB.toString().replaceAll("\\s*", "");
    }


    private static void printMessage(final InputStream input) {
        new Thread(new Runnable() {
            @Override
            public void run() {
                Reader reader = new InputStreamReader(input);
                BufferedReader bf = new BufferedReader(reader);
                String line = null;
                try {
                    while ((line = bf.readLine()) != null) {
                        System.out.println(line);
                    }
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }).start();
    }
}

4.TestOcr 测试代码

package com.lk.integutils.utils;

import java.io.File;
import java.io.IOException;

public class TestOcr {

    /**
     * @param args
     */
    public static void main(String[] args) {
        //输入图片地址
        String path = "d://1640144341(1).png";
        try {
            String valCode = new OCRUtil().recognizeText(new File(path), "png");
            System.out.println(valCode);
        } catch (IOException e) {
            e.printStackTrace();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

}

结尾

效果不咋的,需要调教

参考文章

mall4j: https://segmentfault.com/a/1190000039362377
SyKay: https://www.jianshu.com/p/f7cb0b3f337a

上一篇:经常使用的几种OCR文档扫描工具|无水印|避免智商税


下一篇:【论文阅读】Beyond OCR + VQA: 将OCR融入TextVQA的执行流程中形成更鲁棒更准确的模型