java實(shí)現(xiàn)圖片文字識(shí)別ocr
最近在開(kāi)發(fā)的時(shí)候需要識(shí)別圖片中的一些文字,網(wǎng)上找了相關(guān)資料之后,發(fā)現(xiàn)google有一個(gè)離線的工具,以下為java使用的demo
在此之前,使用這個(gè)工具需要在本地安裝OCR工具:
下面一個(gè)是一定要安裝的離線包,建議默認(rèn)安裝
上面一個(gè)是中文的語(yǔ)言包,如果網(wǎng)絡(luò)可以FQ的童鞋可以在安裝的時(shí)候就選擇語(yǔ)言包在線安裝,有多種語(yǔ)言可供選擇,默認(rèn)只有英文的
exe安裝好之后,把上面一個(gè)文件拷到安裝目錄下tessdata文件夾下
如C:\Program Files (x86)\Tesseract-OCR\tessdata下
然后下面兩個(gè)是可選包,如果圖片不做臨時(shí)文件處理的話,可以不需要帶的
首先是一個(gè)臨時(shí)文件生成用的類以防源文件損壞,參考某位博友的例子@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"); //設(shè)置文件隱藏 return new File(strB.toString()); } }
下面是真正識(shí)別的內(nèi)容:
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"; //英文字母小寫(xiě)l,并非數(shù)字1 private final String EOL = System.getProperty("line.separator"); private String tessPath = "C://Program Files (x86)//Tesseract-OCR";//ocr默認(rèn)安裝路徑 private String transname="chi_sim";//默認(rèn)中文語(yǔ)言包,識(shí)別中文 /** * 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"); //設(shè)置文件隱藏 StringBuffer strB = new StringBuffer(); List<String> cmd = new ArrayList<String>(); if(OS.isWindowsXP()){ cmd.add(tessPath+"http://tesseract"); }else if(OS.isLinux()){ cmd.add("tesseract"); }else{ cmd.add(tessPath+"http://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();//刪除臨時(shí)正在工作文件 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(); } }
在實(shí)驗(yàn)中發(fā)現(xiàn),如果對(duì)有多個(gè)文字的大圖進(jìn)行直接識(shí)別的話,效果可能比較差,所以可以參考另一篇切圖的博文,將圖片取一塊之后再識(shí)別
http://chabaoo.cn/article/121231.htm ←我是鏈接
這樣成功率會(huì)提高很多。
以上為離線識(shí)別版本,效率因圖而已,具體使用的時(shí)候可以總結(jié)分析,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
相關(guān)文章
一文搞懂Java中對(duì)象池的實(shí)現(xiàn)
池化并不是什么新鮮的技術(shù),它更像一種軟件設(shè)計(jì)模式,主要功能是緩存一組已經(jīng)初始化的對(duì)象,以供隨時(shí)可以使用。本文將為大家詳細(xì)講講Java中對(duì)象池的實(shí)現(xiàn),需要的可以參考一下2022-07-07在SpringBoot中通過(guò)jasypt進(jìn)行加密解密的方法
今天小編就為大家分享一篇關(guān)于在SpringBoot中通過(guò)jasypt進(jìn)行加密解密的方法,小編覺(jué)得內(nèi)容挺不錯(cuò)的,現(xiàn)在分享給大家,具有很好的參考價(jià)值,需要的朋友一起跟隨小編來(lái)看看吧2019-01-01深入了解Java SpringBoot自動(dòng)裝配原理
在使用springboot時(shí),很多配置我們都沒(méi)有做,都是springboot在幫我們完成,這很大一部分歸功于springboot自動(dòng)裝配。本文將詳細(xì)為大家講解SpringBoot的自動(dòng)裝配原理,需要的可以參考一下2022-03-03Java 中jasperReport實(shí)現(xiàn)動(dòng)態(tài)列打印的實(shí)現(xiàn)代碼
這篇文章主要介紹了Java 中jasperReport實(shí)現(xiàn)動(dòng)態(tài)列打印的實(shí)現(xiàn)代碼的相關(guān)資料,希望通過(guò)本文大家能掌握這部分內(nèi)容,需要的朋友可以參考下2017-09-09Spring使用Jackson實(shí)現(xiàn)轉(zhuǎn)換XML與Java對(duì)象
這篇文章主要為大家詳細(xì)介紹了Spring如何使用Jackson實(shí)現(xiàn)轉(zhuǎn)換XML與Java對(duì)象,文中的示例代碼講解詳細(xì),感興趣的小伙伴可以跟隨小編一起學(xué)習(xí)一下2024-02-02IDEA安裝后找不到.vmoptions文件的問(wèn)題及解決
這篇文章主要介紹了IDEA安裝后找不到.vmoptions文件的問(wèn)題及解決方案,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2023-04-04IDEA?+?Maven環(huán)境下的SSM框架整合及搭建過(guò)程
這篇文章主要介紹了IDEA?+?Maven環(huán)境下的SSM框架整合及搭建過(guò)程,本文通過(guò)圖文并茂的形式給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2022-01-01