一聚教程网:一个值得你收藏的教程网站

热门教程

java实现图片文字识别ocr

时间:2022-06-29 01:23:59 编辑:袖梨 来源:一聚教程网

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

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

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

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

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

如C:Program Files (x86)Tesseract-OCRtessdata下

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

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

packageorg.ink.image.textrz;
 
importjava.awt.image.BufferedImage;
importjava.io.File;
importjava.io.IOException;
importjava.util.Iterator;
importjava.util.Locale;
  
importjavax.imageio.IIOImage;
importjavax.imageio.ImageIO;
importjavax.imageio.ImageReader;
importjavax.imageio.ImageWriteParam;
importjavax.imageio.ImageWriter;
importjavax.imageio.metadata.IIOMetadata;
importjavax.imageio.stream.ImageInputStream;
importjavax.imageio.stream.ImageOutputStream;
  
importcom.sun.media.imageio.plugins.tiff.TIFFImageWriteParam;
  
publicclassImageIOHelper {
  privateLocale locale=Locale.CHINESE;
  /**
   * user set locale Construct
   * @param locale
   */
  publicImageIOHelper(Locale locale){
    this.locale=locale;
  }
   
  /**
   * default construct using default locale Locale.CHINESE
   */
  publicImageIOHelper(){
     
  }
  /**
   * 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
   */
  publicFile createImage(File imageFile, String imageFormat)throwsIOException { 
    Iterator readers = ImageIO.getImageReadersByFormatName(imageFormat); 
    ImageReader reader = readers.next(); 
    ImageInputStream iis = ImageIO.createImageInputStream(imageFile); 
    reader.setInput(iis); 
    IIOMetadata streamMetadata = reader.getStreamMetadata(); 
    TIFFImageWriteParam tiffWriteParam =newTIFFImageWriteParam(Locale.CHINESE); 
    tiffWriteParam.setCompressionMode(ImageWriteParam.MODE_DISABLED); 
    Iterator writers = ImageIO.getImageWritersByFormatName("tiff"); 
    ImageWriter writer = writers.next(); 
    BufferedImage bi = reader.read(0); 
    IIOImage image =newIIOImage(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(); 
    returntempFile; 
  } 
  /**
   * add suffix to tempfile
   * @param imageFile
   * @return
   * @throws IOException
   */
  privateFile tempImageFile(File imageFile)throwsIOException { 
    String path = imageFile.getPath(); 
    StringBuffer strB =newStringBuffer(path); 
    strB.insert(path.lastIndexOf('.'),"_text_recognize_temp");
    String s=strB.toString().replaceFirst("(?<=//.)(//w+)$","tif");
    Runtime.getRuntime().exec("attrib "+"""+s+"""+" +H");//设置文件隐藏
    returnnewFile(strB.toString());
  } 
   
}

下面是真正识别的内容:

packageorg.ink.image.textrz;
 
importjava.io.BufferedReader; 
importjava.io.File; 
importjava.io.FileInputStream;
importjava.io.IOException;
importjava.io.InputStreamReader; 
importjava.util.ArrayList; 
importjava.util.List;
importjava.util.Locale;
 
importorg.jdesktop.swingx.util.OS; 
 
/**
 * TEXT Recognize Utils
 * @author ink.Flower
 *
 */
publicclassOCRUtil {
  privatefinalString LANG_OPTION ="-l";//英文字母小写l,并非数字1 
  privatefinalString EOL = System.getProperty("line.separator"); 
  privateString tessPath ="C://Program Files (x86)//Tesseract-OCR";//ocr默认安装路径
  privateString 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
   */
  publicOCRUtil(String tessPath,String transFileName){
    this.tessPath=tessPath;
    this.transname=transFileName;
  }
  /**
   * Construct method of OCR,default path is "C://Program Files (x86)//Tesseract-OCR"
   */
  publicOCRUtil(){   }
   
  publicString getTessPath() {
    returntessPath;
  }
  publicvoidsetTessPath(String tessPath) {
    this.tessPath = tessPath;
  }
  publicString getTransname() {
    returntransname;
  }
  publicvoidsetTransname(String transname) {
    this.transname = transname;
  }
  publicString getLANG_OPTION() {
    returnLANG_OPTION;
  }
  publicString getEOL() {
    returnEOL;
  }
   
  /**
   * recognize text in image
   * @param imageFile
   * @param imageFormat
   * @return text recognized in image
   * @throws Exception
   */
  publicString recognizeText(File imageFile,String imageFormat)throwsException{ 
    File tempImage =newImageIOHelper().createImage(imageFile,imageFormat); 
    returnocrImages(tempImage, imageFile); 
  } 
   
  /**
   * recognize text in image
   * @param imageFile
   * @param imageFormat
   * @param locale
   * @return text recognized in image
   * @throws Exception
   */
  publicString recognizeText(File imageFile,String imageFormat,Locale locale)throwsException{ 
    File tempImage =newImageIOHelper(locale).createImage(imageFile,imageFormat);
    returnocrImages(tempImage, imageFile);
       
  }
  /**
   *
   * @param tempImage
   * @param imageFile
   * @return
   * @throws IOException
   * @throws InterruptedException
   */
  privateString ocrImages(File tempImage,File imageFile)throwsIOException, InterruptedException{
    File outputFile =newFile(imageFile.getParentFile(),"output");
    Runtime.getRuntime().exec("attrib "+"""+outputFile.getAbsolutePath()+"""+" +H");//设置文件隐藏
    StringBuffer strB =newStringBuffer(); 
    List cmd =newArrayList(); 
    if(OS.isWindowsXP()){ 
      cmd.add(tessPath+"//tesseract"); 
    }elseif(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 =newProcessBuilder(); 
    pb.directory(imageFile.getParentFile()); 
    cmd.set(1, tempImage.getName()); 
    pb.command(cmd); 
    pb.redirectErrorStream(true); 
    Process process = pb.start(); 
    intw = process.waitFor(); 
    tempImage.delete();//删除临时正在工作文件    
    if(w==0){ 
      BufferedReader in =newBufferedReader(newInputStreamReader(newFileInputStream(outputFile.getAbsolutePath()+".txt"),"UTF-8")); 
      String str; 
      while((str = in.readLine())!=null){ 
        strB.append(str).append(EOL); 
      } 
      in.close(); 
    }else{ 
      String msg; 
      switch(w){ 
      case1: 
        msg ="Errors accessing files.There may be spaces in your image's filename."; 
        break; 
      case29: 
        msg ="Cannot recongnize the image or its selected region."; 
        break; 
      case31: 
        msg ="Unsupported image format."; 
        break; 
      default: 
        msg ="Errors occurred."; 
      } 
      tempImage.delete(); 
      thrownewRuntimeException(msg); 
    } 
    newFile(outputFile.getAbsolutePath()+".txt").delete(); 
    returnstrB.toString();
  }
} 

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

这样成功率会提高很多。

热门栏目