您当前的位置:首页 > 计算机 > 编程开发 > 人工智能

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

时间:05-23来源:作者:点击数:

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

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

方便获取更多学习、工作、生活信息请关注本站微信公众号城东书院 微信服务号城东书院 微信订阅号
推荐内容
相关内容
栏目更新
栏目热门