ocr总结

工作关系,这一周对ocr进行了一下研究。这里进行一下总结

        目前主流的技术有:1、tesseract-ocr

                                         2、sikulix(其底层是tesseract-ocr,只是他的封装用起来很方便)

                                         3、百度-ocr


        在这里比较一下他们各自的优缺点和使用场景。

        一、tesseract-ocr

        tesseract-ocr 主要用来解决英语,数字的文字识别。从3.0开始才加入中文,它对中文的支持相当的不靠谱。如果要用它来识别中文的话,业务场景需要被识别的图片中的文字有相当的规律。因为它提供了训练的功能,可以让ocr不断进行学习。所以也可以用来处理简单的干扰不大的数字加字母的验证码。他还有一个有点是,不需要任何网络请求,直接可以在本机进行处理。最后,他是开源的。

        环境搭建:需要安装tesseract-ocr,然后引入jai_imageio.jar和javacsv.jar。

        java demo代码,其实原理很简单,通过cmd调用命令即可

    private final static String LANG_OPTION = "-l";  //英文字母小写l,并非数字1  
    private final static String EOL = System.getProperty("line.separator");  
    private final static String tessPath = "C:\\Program Files (x86)\\Tesseract-OCR";  
	
	public static String getString(File imageFile, String imageFormat) throws Exception {
		
		//File tempImage = ImgUtil.createImage(imageFile,imageFormat);  
        File outputFile = new File(imageFile.getParentFile(),"output");  
        StringBuffer strB = new StringBuffer();  
        List cmd = new ArrayList();  
        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("eng");  
        //cmd.add("eng");  
          
        ProcessBuilder pb = new ProcessBuilder();  
        pb.directory(imageFile.getParentFile());  
          
        cmd.set(1, imageFile.getAbsolutePath());  
        pb.command(cmd);  
        pb.redirectErrorStream(true);  
          
        Process process = pb.start();  
        System.out.println(cmd);
        //tesseract.exe 1.jpg 1 -l chi_sim  
        int w = process.waitFor();  
          
        //删除临时正在工作文件  
        //tempImage.delete();  
        imageFile.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();  
            imageFile.delete();
            throw new RuntimeException(msg);  
        }  
        new File(outputFile.getAbsolutePath()+".txt").delete();  
        return strB.toString();    
		
	}  


        训练:需要工具jTessBoxEditor。

        1、将需要用来训练的图片转换为tif格式,文件名改为[语言]

        2、生成box文件 调用命令tesseract.exe eng.normal.exp0.tif eng.normal.exp0 -l eng batch.nochop makebox

        3、用jTessBoxEditor打开tif文件,进行纠正
        ocr总结_第1张图片

            4、纠正完后进行保存,将会保存box文件。

            5、进行训练,调用命令tesseract.exe eng.normal.exp0.tif eng.normal.exp0  nobatch box.train

            6、生成tr文件,可以批量指定box文件,调用命令 unicharset_extractor.exe eng.normal.exp0.box eng.normal.exp1.box

            7、创建字体设置文件,font_properties,内容为 字体名 0 0 0 0 0,比如normal 0 0 0 0 0

            8、生成unicharset文件,可以批量指定tr文件,调用命令mftraining.exe -F font_properties -U unicharset -O eng.unicharset eng.normal.exp0.tr eng.normal.exp1.tr

            9、生成关键文件,可以批量指定tr文件,调用命令cntraining.exe eng.normal.exp0.tr eng.normal.exp1.tr

            10、将生成的inttemp、pffmtable、normproto、shapetable文件修改文件名,加入前缀"字体名."

            11、合并成语言包文件,调用命令combine_tessdata 语言名

           

             二、sikulix

             sikulix由于底层使用的是tesseract-ocr,所以优缺点都是一样的,sikulix相比于tesseract-ocr来说,优点在于封装了方便的api,而且提供了截图功能,并且直接采用字节流,不用创建文件。最后,它也是开源的。

             关于sikulix使用tesseract-ocr的功能可以看我之前写的篇文章http://blog.csdn.net/guduyishuai/article/details/78331862,我就不赘述了。


             三、百度-ocr

             百度-ocr基于百度强大的人工智能,百度大脑,因此非常可靠。对于中文的识别也是相当精准的,同时提供了多种语言,包括android移动端的sdk,相当的方便。它的缺点是必须有网络,而且不是开源的,每天超过500次调用将收费。

             我之前使用过android、和http api的方式,都很简单。这里来说一下python的方式,因为坑还是比较多的。

             python版本提供了基于python2.7+和python3.+版本的模块。这里插一句,python2和python3的差异性很大,而且不兼容,这就造成很多人的机子上两个版本都有,这时候在pip的时候要注意是使用哪个版本的。

             有两个方式来区分版本,方式一:修改python.exe文件名。方式二:使用py -2/-3 -m 命令。

             我这里是使用python3.4版本来进行pip的,于是坑开始了。

             首先,遇到了这个错误


             这个错误实际上是python的一个bug,解决方案就是升级相应的安装工具


 

             注意,不要用阿里的镜像,因为目前为止,阿里的镜像还没有更新最新的版本

             最后就可以成功地调用pip获取百度的api了


             到此为止,可以写相应的python代码了。如果最后能成功执行,就ok了。但是很可能还缺少不少模块,这时候就根据报错信息进行pip,我把我遇到的记录一下






              在安装image时要注意,它提示的模块是PLT,而且很可能安装失败,这个时候需要重新安装pillow


               下面我们来看一下python的demo

#! /usr/local/bin/python
# encoding: utf-8

'''
Created on 2017年9月26日

@author: wulinfeng
@date: 2017-09-30
'''

import sys
from aip import AipOcr

APP_ID = '你的APP_ID'
API_KEY = '你的API_KEY'
SECRET_KEY = '你的SECRET_KEY'

aipOcr = AipOcr(APP_ID, API_KEY, SECRET_KEY)

# 读取图片
def get_file_content(filePath):
    with open(filePath, 'rb') as fp:
        return fp.read()
#       data = ''
#       file = open(filePath)  
#       try:  
#           data = file.read()  
#       finally:  
#           file.close()  
#           return data

def cognize_text(filePath):
    result = aipOcr.basicAccurate(get_file_content(filePath));
    return result
    
# 调用通用文字识别接口
print(cognize_text(sys.argv[1]))

         最后吐槽一下jython

         到目前为止jython还不支持python3,而且使用中非常不方便,而且也有一些坑。最新版的jython-2.7.0可能会报错如下

ocr总结_第2张图片

          这必须在java中进行设置,python.import.site=false

static {
		
		Properties props = new Properties();
		props.put("python.home", "path to the Lib folder");
		props.put("python.console.encoding", "UTF-8");
		props.put("python.security.respectJavaAccessibility", "false");
		props.put("python.import.site", "false");
		Properties preprops = System.getProperties();
		PythonInterpreter.initialize(preprops, props, new String[0]);
		
	}
            然后,还有一个坑是jython的环境路径和python并不是统一的,所以单独能运行的python脚本,并不能在java中调用成功,会报错,说某些module找不到,这时候需要执行sys的相关函数来进行设置

PythonInterpreter interpreter = new PythonInterpreter();  
			
			PySystemState sys = Py.getSystemState();
			interpreter.exec("import sys");
			interpreter.exec("sys.path.append('C:/Python34/Lib')");
			interpreter.exec("sys.path.append('C:/Python34/Lib/site-packages')");
			interpreter.exec("from aip import AipOcr");
             如果是python2.7+,name就可以用如下的方法

public static String callFunction(String file, String fnName, String ... args) {
		
		try {
			
			PythonInterpreter interpreter = new PythonInterpreter();  
			
			PySystemState sys = Py.getSystemState();
			interpreter.exec("import sys");
			interpreter.exec("sys.path.append('C:/Python34/Lib')");
			interpreter.exec("sys.path.append('C:/Python34/Lib/site-packages')");
			interpreter.exec("from aip import AipOcr");
			
			interpreter.execfile(PythonUtil.getUrl(file));  
			PyFunction func = (PyFunction)interpreter.get(fnName,PyFunction.class);
			
			PyString[] ps = new PyString[args.length];
					
			for(int i=0; i
          
PythonUtil.callFunction(Resource.PYTHON_BAIDU_OCR,  "cognize_text", "D:/test666.png");

            如果python3+,那么就只能使用jdk中的方法调用cmd命令来进行执行脚本

public static String execScript(String file, String ... args) {
		
		StringBuffer result = new StringBuffer();
		
		try {
			StringBuffer cmd = new StringBuffer();
			cmd.append("python "+file);
			Arrays.asList(args)
			         .stream()
			         .forEach(arg -> {
			        	 cmd.append(" "+arg);
			         });
			logger.log(Level.INFO, "cmd="+cmd.toString());
			Process pr = Runtime.getRuntime().exec(cmd.toString());
			BufferedReader in = new BufferedReader(new InputStreamReader(pr.getInputStream(), Charset.forName("GBK")));
		    String line = "";
		    while ((line = in.readLine()) != null) {
		    	result.append(line);
	    	}
	    	in.close();
	    	pr.waitFor();
		} catch (Exception e) {
			e.printStackTrace();
		}
		
		return result.toString();
		
	}

PythonUtil.execScript(PythonUtil.getUrl(Resource.PYTHON_BAIDU_OCR),  "D:/test666.png");





      

你可能感兴趣的:(java,python)