欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

图像文字识别(二):java调用tesseract 识别图片文字

程序员文章站 2022-04-15 13:37:37
...
  在JAVA中调用tesseract识别图片的文字内容,主要有两种方式:cmd方式,tess4j方式。在这篇博客中,主要记录一下通过cmd命令行的方式。cmd方式,就是通过在java中调用命令行,来执行tesseract,它的原理就是上篇博客所写的内容。


步骤:

(1)导入两个jar包:jai_imageio-1.1.1.jar 和 swingx-1.6.1.jar

(2)编写ImageIOHelper类,用于创建临时图片文件,防止损坏初始文件

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.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()); 
	    }    
}

(3)创建OCRUtil工具类,用于进行图片文字识别:

import java.io.BufferedReader;    
import java.io.File;    
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStreamReader;    
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");    
    private String tessPath = "D://Tesseract//Tsseract-OCR//Tesseract-OCR";//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;
    }
    
    
    /**
     * @param 需要识别的文件
     * @param 文件的格式
     * @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());    
        pb.command(cmd);//设置要执行的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
        
        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*", ""); 
    }
}

(4)创建测试类Test:

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

/** 
* @version 创建时间:2018年4月25日 下午5:09:19 
* 类说明:测试类
*/
public class Test {

    public static void main(String[] args) {

	try {
            //图片文件:此图片是需要被识别的图片路径 
            File file = new File("C://Users//1_20180208150251_x4hzz//1.png");
            //String recognizeText = new OCRHelper().recognizeText(file);
            String recognizeText = new OCRUtil().recognizeText(file, "png");
            System.out.print(recognizeText + "\t");

        } catch (IOException e) {
            e.printStackTrace();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

至此,只要传入需要识别的图片,就可以识别出图片中的文字的内容了。