首页 > 编程 > Java > 正文

java实现图片文字识别ocr

2019-11-26 11:38:58
字体:
来源:转载
供稿:网友

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

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

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

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

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

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

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

首先是一个临时文件生成用的类以防源文件损坏,参考某位博友的例子@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();   }}  

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

//www.VeVB.COm/article/121231.htm  ←我是链接

这样成功率会提高很多。

以上为离线识别版本,效率因图而已,具体使用的时候可以总结分析,希望对大家的学习有所帮助,也希望大家多多支持武林网。

发表评论 共有条评论
用户名: 密码:
验证码: 匿名发表