摘要

Java + OCR 提取图片文字。在电商平台中,平台可能需要对商家一些营业执照,身份证件件进行审核,我们可能需要证件中的编号进行提取。当少量商家的时候,可以人工审核,把证件中的编号提取出来;当商家数量变多的时候,平台审核就很耗费人工。这个时候我们就自然而然想到能不能把图片中的文字提取出来。下面我们就来了解一下OCR图片文字提取。

SpringBoot实战电商项目mall4j 地址 : [https://gitee.com/gz-yami/mall4j]

Java+Tesseract_OCR 图片文字提取初次入门

可以调用第三放接口,进行图片文字提取,例如:百度API

这里我们自己在本地来做一个图片文字提取,使用Java+Tesseract的方式

环境准备
win10,jdk1.8, idea,maven

下载tesseract3.02,中文词库
首先必须要有Java环境JDK

1.下载安装tesseract3.02

2.下载中文词库chi_sim.traineddata

百度网盘:
链接:https://pan.baidu.com/s/1VYx6...
提取码:hsr7

3.将chi_sim.traineddata放在tessdata目录下

4.打开\tessdata\configs目录下的digits文件,将
tessedit_char_whitelist 0123456789-. 改为 tessedit_char_whitelist 0123456789x.

5.配置环境变量(tesseract3.02的安装目录)


6.测试是否安装完成

WIN+R打开cmd命令

输入tesseract

出现表示安装完成

Usage:tesseract imagename outputbase [-l lang] [-psm pagesegmode] [configfile...]

pagesegmode values are:

0 = Orientation and script detection (OSD) only.

1 = Automatic page segmentation with OSD.

2 = Automatic page segmentation, but no OSD, or OCR

3 = Fully automatic page segmentation, but no OSD. (Default)

4 = Assume a single column of text of variable sizes.

5 = Assume a single uniform block of vertically aligned text.

6 = Assume a single uniform block of text.

7 = Treat the image as a single text line.

8 = Treat the image as a single word.

9 = Treat the image as a single word in a circle.

10 = Treat the image as a single character.

-l lang and/or -psm pagesegmode must occur before anyconfigfile.

Single options:

-v --version: version info

--list-langs: list available languages for tesseract engine

提取文字

tesseract C:/pic/1.png C:/pic/1 -l chi_sim

c盘的图片,生成1.txt(提取到的文字内容)

-l :不是1 是英文字母L对应的小写字母l

chi_sim 中文词库

java 项目中导入依赖

 <dependency>
            <groupId>net.sourceforge.tess4j</groupId>
            <artifactId>tess4j</artifactId>
            <version>3.2.1</version>
            <exclusions>
                <exclusion>
                    <groupId>com.sun.jna</groupId>
                    <artifactId>jna</artifactId>
                </exclusion>
            </exclusions>
        </dependency>
        <dependency>
            <groupId>net.java.dev.jna</groupId>
            <artifactId>jna</artifactId>
            <version>4.1.0</version>
        </dependency>
        <!-- https://mvnrepository.com/artifact/javax.media/jai_imageio -->
        <dependency>
            <groupId>javax.media</groupId>
            <artifactId>jai_imageio</artifactId>
            <version>1.1.1</version>
        </dependency>

        <!-- https://mvnrepository.com/artifact/org.swinglabs/swingx -->
        <dependency>
            <groupId>org.swinglabs</groupId>
            <artifactId>swingx</artifactId>
            <version>1.6.1</version>
        </dependency>

代码
ImageIOHelper.class

package com.example.excel.excelexportodb.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;
//import com.sun.media.imageio.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());
    }
}

OCRUtil.class

package com.example.excel.excelexportodb.Utils;
import java.io.*;
import java.util.ArrayList;
import java.util.List;
import java.util.Locale;

import org.jdesktop.swingx.util.OS;

/**
 * 类说明:OCR工具类
 */
public class OCRUtil {
    private final String LANG_OPTION = "-l";
    //英文字母小写l,并非阿拉伯数字1

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

    /**
     * ocr的安装路径
     */
    private String tessPath =  "D://tess4j//tess4j-src//tesseract-ocr-set-3.0//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*", "");
    }

//    public static void main(String[] args) throws IOException, InterruptedException {
//    String cmd = "cmd /c dir c:\\windows";
//    final Process process = Runtime.getRuntime().exec(cmd);
//    printMessage(process.getInputStream());
//    printMessage(process.getErrorStream());
//    int value = process.waitFor();
//    System.out.println(value);
//    }
    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();
    }
}

主函数

 public static void main(String[] args) throws TesseractException {
        String path = "D://1.png";
        System.out.println("ORC Test Begin......");
        try {
            String valCode = new OCRUtil().recognizeText(new File(path), "png");
            System.out.println(valCode);
        } catch (IOException e) {
            e.printStackTrace();
        } catch (Exception e) {
            e.printStackTrace();
        }
        System.out.println("ORC Test End......");


    }

识别图片

ORC Test Begin......

测试123

ORC Test End......

最终识别效果一般,一些复杂文字识别出现乱码,这个时候就需要我们去训练词库了

训练越多就识别的越精确

SpringBoot实战电商项目mall4j 地址 : [https://gitee.com/gz-yami/mall4j]

mall4j
26 声望0 粉丝