【圖片識別】java 圖片文字識別 ocr (轉)

http://www.cnblogs.com/inkflower/p/6642264.htmlhtml

最近在開發的時候須要識別圖片中的一些文字,網上找了相關資料以後,發現google有一個離線的工具,如下爲java使用的demojava

在此以前,使用這個工具須要在本地安裝OCR工具:ios

下面一個是必定要安裝的離線包,建議默認安裝api

上面一個是中文的語言包,若是網絡能夠FQ的童鞋能夠在安裝的時候就選擇語言包在線安裝,有多種語言可供選擇,默認只有英文的網絡

exe安裝好以後,把上面一個文件拷到安裝目錄下tessdata文件夾下app

如C:\Program Files (x86)\Tesseract-OCR\tessdata下工具

而後下面兩個是可選包,若是圖片不作臨時文件處理的話,能夠不須要帶的ui

首先是一個臨時文件生成用的類以防源文件損壞,參考某位博友的例子@Gunnerthis

 

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

下面是真正識別的內容:google

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也能夠找找

相關文章
相關標籤/搜索