zoukankan      html  css  js  c++  java
  • java 图片文字识别 ocr

    最近在开发的时候需要识别图片中的一些文字,网上找了相关资料之后,发现google有一个离线的工具,以下为java使用的demo

    在此之前,使用这个工具需要在本地安装OCR工具:

    下面一个是一定要安装的离线包,建议默认安装

    上面一个是中文的语言包,如果网络可以FQ的童鞋可以在安装的时候就选择语言包在线安装,有多种语言可供选择,默认只有英文的

    exe安装好之后,把上面一个文件拷到安装目录下tessdata文件夹下

    如C:Program Files (x86)Tesseract-OCR essdata下

    然后下面两个是可选包,如果图片不做临时文件处理的话,可以不需要带的

    首先是一个临时文件生成用的类以防源文件损坏,参考某位博友的例子@Gunner

    package org.ink.image.textrz;
    
    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;
        /**
         * user set locale Construct
         * @param locale
         */
        public ImageIOHelper(Locale locale){
            this.locale=locale;
        }
        
        /**
         * default construct using default locale Locale.CHINESE
         */
        public ImageIOHelper(){
            
        }
        /**
         * create tempFile of Image in order to prevent damaging original file
         * @param imageFile
         * @param imageFormat like png,jps .etc
         * @return TempFile of Image
         * @throws IOException
         */
        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();    
            TIFFImageWriteParam tiffWriteParam = new TIFFImageWriteParam(Locale.CHINESE);    
            tiffWriteParam.setCompressionMode(ImageWriteParam.MODE_DISABLED);    
            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;    
        }    
        /**
         * add suffix to tempfile
         * @param imageFile
         * @return
         * @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()); 
        }    
        
    }  

    下面是真正识别的内容:

    package org.ink.image.textrz;
    
    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;    
    
    /**
     * TEXT Recognize Utils
     * @author ink.Flower
     *
     */
    public class OCRUtil { 
        private final String LANG_OPTION = "-l";  //英文字母小写l,并非数字1    
        private final String EOL = System.getProperty("line.separator");    
        private String tessPath = "C://Program Files (x86)//Tesseract-OCR";//ocr默认安装路径
        private String transname="chi_sim";//默认中文语言包,识别中文
        
        /**
         * Construct method of OCR ,set Tesseract-OCR install path
         * @param tessPath Tesseract-OCR install path
         * @param transFileName traningFile name like eng.traineddata
         */
        public OCRUtil(String tessPath,String transFileName){
            this.tessPath=tessPath;
            this.transname=transFileName;
        }
        /**
         * Construct method of OCR,default path is "C://Program Files (x86)//Tesseract-OCR"
         */
        public OCRUtil(){     }
        
        public String getTessPath() {
            return tessPath;
        }
        public void setTessPath(String tessPath) {
            this.tessPath = tessPath;
        }
        public String getTransname() {
            return transname;
        }
        public void setTransname(String transname) {
            this.transname = transname;
        }
        public String getLANG_OPTION() {
            return LANG_OPTION;
        }
        public String getEOL() {
            return EOL;
        }
        
        /**
         * recognize text in image
         * @param imageFile
         * @param imageFormat
         * @return text recognized in image
         * @throws Exception
         */
        public String recognizeText(File imageFile,String imageFormat)throws Exception{    
            File tempImage = new ImageIOHelper().createImage(imageFile,imageFormat);    
            return ocrImages(tempImage, imageFile);   
        }    
        
        /**
         * recognize text in image
         * @param imageFile
         * @param imageFormat
         * @param locale
         * @return text recognized in image
         * @throws Exception
         */
        public String recognizeText(File imageFile,String imageFormat,Locale locale)throws Exception{    
            File tempImage = new ImageIOHelper(locale).createImage(imageFile,imageFormat);
            return ocrImages(tempImage, imageFile);
               
        }
        /**
         * 
         * @param tempImage
         * @param imageFile
         * @return
         * @throws IOException
         * @throws InterruptedException
         */
        private String ocrImages(File tempImage,File imageFile) throws IOException, InterruptedException{
            File outputFile = new File(imageFile.getParentFile(),"output");
            Runtime.getRuntime().exec("attrib "+"""+outputFile.getAbsolutePath()+"""+" +H"); //设置文件隐藏
            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(transname);    
            ProcessBuilder pb = new ProcessBuilder();    
            pb.directory(imageFile.getParentFile());    
            cmd.set(1, tempImage.getName());    
            pb.command(cmd);    
            pb.redirectErrorStream(true);    
            Process process = pb.start();    
            int w = process.waitFor();    
            tempImage.delete();//删除临时正在工作文件         
            if(w==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();    
            }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(); 
        }
    }    

     在实验中发现,如果对有多个文字的大图进行直接识别的话,效果可能比较差,所以可以参考另一篇切图的博文,将图片取一块之后再识别

    http://www.cnblogs.com/inkflower/p/6642089.html     ←我是链接

    这样成功率会提高很多。

    以上为离线识别版本,效率因图而已,具体使用的时候可以总结分析

    另外,博主也在网上看到百度也有图片文字识别的工具

    百度OCR企业版

    以上这个貌似是付费的,如果要免费的可以网上找找,另外API也可以找找

    Ink.Flower@china
  • 相关阅读:
    四叉树空间索引原理及其实现
    深入理解空间搜索算法 ——数百万数据中的瞬时搜索
    空间索引
    Microsoft.Office.Core 引用以及 Microsoft.Office.Core.MsoTriState 的问题
    Visual studio 2017 中的Javascript智能提示与调试
    EasyUI Tooltip 提示框
    java编程中的断言工具类(org.springframework.util.Assert)
    Guava学习笔记:Google Guava 类库简介
    Jquery autocomplete插件
    easyui-textbox
  • 原文地址:https://www.cnblogs.com/inkflower/p/6642264.html
Copyright © 2011-2022 走看看