【Java学习笔记】2015.1.6 tesseract_orc java上的一种实现方法

今天想着把以前做过的一个Android的文字检测识别应用好好的回顾一下,因为以前写java程序,目的就是能用就行,不会仔细看每一个部分代码,也不会记他们的用法,不回会去查API,借鉴别人的例程,用过就忘了,现在想着要改变,于是就回顾了一番。

之前检测用到的是Tesseract_OCR,之所以能在Android的上运行,是因为黑暗伯爵大神已经把tess-two(为android写的tesseract-tools)编译好了,然后我直接用的。我还是小白,完全不懂编译那些,如果让我自己搞.... 反正最后编译成so文件(这个是linux平台下的动态链接库,可以类比dll),然后我用编译好的so文件,以及jar包导入到工程,照葫芦画瓢把文字识别部分和自己之前看论文写的文字检测部分合到一起,然后百度了怎么调用摄像头,然后写了一个摄像头拍照,然后检测文字所在区域,处理,然后识别的应用。以后有时间会详细的重新把应用梳理一遍,然后记录,当然这不是今天的重点。如果对Android上如何做OCR感兴趣,可以参考 这里 。

回到正题,前几天同学问我以前做的文字识别是咋搞得,他想用用,我于是就想把程序移回来到java上,结果我百度才发现原来还有另外一种思路,那就是执行exe进程。先在pc上安装好tesseract_orc,然后jvm运行命令行跑识别程序,完成识别后结果写入txt,最后读取txt把内容返回到java程序中。这么想想也行,于是便试了试。(PS:我是后来才发现也有Java的API tess4j,参考 这里

然后就是讲自己具体怎么实现:

工程也就两部分,一部分是GUI,反正我现在对于Java的基础知识薄弱,然后常用类也用的不多,所以借此机会正好熟悉。

GUI主要用到javax.swing包和java.awt包,swing主要写组件,awt是事件(其实awt也可以写组件),但是说swing是对awt中组建的优化,所以现在常用swing。GUI里面比较重要的概念还是容器,组件必须放到容器里面才能显示,常用frame和dialog。我这次写GUI用到jframe,jbutton,filedialog,JLabel,imageicon这几个类

界面如下

  • 其中的按钮用的JButton:"push" 按钮的实现,可以设置监听器。
  • 按钮设置了监听器,“打开图片”弹出Filedoalog,选择图片文件,“识别”新建文字识别类,进行识别返回结果:FileDialog 类显示一个对话框窗口,用户可以从中选择文件。
  • 图片显示和文字显示用的JLabel:JLabel 对象可以显示文本、图像或同时显示二者。可以通过设置垂直和水平对齐方式,指定标签显示区中标签内容在何处对齐。默认情况下,标签在其显示区内垂直居中对齐。默认情况下,只显示文本的标签是开始边对齐;而只显示图像的标签则水平居中对齐。
  • Jframe建立整个容器
  • Imageicon用来加载图像。Imageicon:一个 Icon 接口的实现,它根据 Image 绘制 Icon。可使用 MediaTracker 预载根据 URL、文件名或字节数组创建的图像,以监视该图像的加载状态。

界面的具体代码我就不贴上来了,值得注意的是图片压缩显示有一个小trick。

imagePath = new String(dirPath+fileName);
imageico = new ImageIcon(imagePath);
int w = imageico.getIconWidth();
int h = imageico.getIconHeight();
double ratio = (double)w/(double)h;
if(ratio>4/3){
    h = (int)(640*h/w);
    w = 640;
}else{
    w = (int)(480*w/h);
    h = 480;
}
imageico.setImage(imageico.getImage().getScaledInstance(w,h,imageico.getImage().SCALE_DEFAULT));
                       

另外,就是文字识别的部分,主要还是一个执行进程的过程,那么首先得下载安装Tesseract_OCR:

安装下载的工作参考 这里

那么这边主要的挑战就是使用java执行进程和做文件io,主要分一下几点:

1.java操作命令行主要用到processbuilder & process 类,出自java.lang

一般都是ProcessBuilder.start() 和 Runtime.exec(ArrayList<String>) 方法创建一个本机进程,并返回 Process 子类的一个实例,该实例可用来控制进程并获得相关信息。Process 类提供了执行从进程输入、执行输出到进程、等待进程完成、检查进程的退出状态以及销毁(杀掉)进程的方法。

Runtime.getRuntime.exec(ArrayList<String> cmd)
processbuilder pb; pb.command(ArrayList<String> cmd);

这里就是用的processbuilder pb,新建一个实例,并且把运行参数保存到字符串表单cmd里,然后pb.command(ArrayList<String> cmd)执行,结果保存到指定txt中;

2.表示文件的类file类 出自java.io
它是文件和目录路径名的抽象表示形式。 
主要方法getName(),getPath(),getParentPath();

在执行命令行时,表示输入的图片,表示输出txt都可以用到file类。

3.读取字节流过程 出自java.io
FileInputStream 从文件系统中的某个文件中获得输入字节。哪些文件可用取决于主机环境,这里可以读取图片。
new FileInputStream(outputFile.getAbsolutePath()) 新建一个文件输入字节流
new InputStreamReader(new FileInputStream(outputFile.getAbsolutePath()),"UTF-8")。文件输入字节流变成文件输入字符流

BufferedReader从字符输入流中读取文本,缓冲各个字符,从而实现字符、数组和行的高效读取。

主要是两种用法还可以这么使用

BufferedReader in = new BufferedReader(new FileReader("foo.in"));

或者
BufferedReader in = new BufferedReader(new InputStreamReader(new FileInputStream("foo.in"),"UTF-8"));

前者不能指定编码,而后者可以。

在最后把txt中文本读取到java程序,进而显示在GUI中用到

识别的代码如下

import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileReader;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.List;

public class textRecognizer{

    private String textResult;
    /**
     * 输出的结果
     */
    private final String EOL = System.getProperty("line.separator");
    //回车
    private String tessPath = "D:\\Tesseract-OCR";
    //tessocr程序所在目录
    public  textRecognizer(String path)
    {
        try
        {
            File imagefile = new File(path);
            textResult = this.recognizeText(imagefile);
        } catch (Exception e)
        {
            e.printStackTrace();
        }
    }

    public String getResult(){
        return textResult;
    }

    private String recognizeText(File imageFile) throws Exception
    {
        /**
         * 设置输出文件的保存的文件目录
         */
        File outputFile = new File(imageFile.getParentFile(),"output");
        StringBuffer strB = new StringBuffer();

        //设置cmd命令行字符串形式
        List<String> cmd = new ArrayList<String>();
        cmd.add(tessPath + "\\tesseract");
        cmd.add(imageFile.getName());
        cmd.add(outputFile.getName());
        cmd.add("-l");
        cmd.add("eng");

        //启动exe进程
        ProcessBuilder pb = new ProcessBuilder();
        pb.directory(imageFile.getParentFile());
        pb.command(cmd);
        pb.redirectErrorStream(true);
        Process process = pb.start();
        //等待此进程完成
        int w = process.waitFor();
        if (w == 0){// 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 recognize the image or its selected region.";
                    break;
                case 31:
                    msg = "Unsupported image format.";
                    break;
                default:
                    msg = "Errors occurred.";
            }
            throw new RuntimeException(msg);
        }
        new File(outputFile.getAbsolutePath()+ ".txt").delete();
        /**
         * 如果做验证码
         * return strB.toString().replaceAll("\\s*", "");
         */
        return strB.toString();
    }
}

可惜的是最后检测的结果一般。

今天写程序期间还有其他的有意思的地方我也有记录。

  • java foreach 遍历,for(File file :testDataDir.listFiles()),jdk1.6后支持。
  • private final String EOL = System.getProperty("line.separator"); 回车换行的字符串表示
时间: 2024-08-24 23:04:13

【Java学习笔记】2015.1.6 tesseract_orc java上的一种实现方法的相关文章

Java学习笔记——浅谈数据结构与Java集合框架(第一篇、List)

横看成岭侧成峰,远近高低各不同.不识庐山真面目,只缘身在此山中. --苏轼 这一块儿学的是云里雾里,咱们先从简单的入手.逐渐的拨开迷雾见太阳.本次先做List集合的三个实现类的学习笔记 List特点:有序,元素可重复.其实它的本质就是一个线性表(下面会说到) 先上图,Java集合有Collection体系和Map体系: 然后简单介绍一下数据结构和算法: 数据结构就是数据和数据之间的关系,好比分子结构,晶体结构.碳原子按照一定的方式组合在一起形成碳分子,碳分子再按照一定方式形成晶体. 算法是对解题

疯狂Java学习笔记(70)-----------挚爱Java

与大家分享! 挚爱Java 10个使用Java最广泛的现实领域 写好Java代码的30条经验总结 Java字符串的substring真的会引起内存泄露么? Java内存的原型及工作原理深度剖析 Java 8中HashMap的性能提升 Java内存的原型及工作原理深度剖析 请不要说自己是Java程序猿 Java程序猿必须掌握的8大排序算法 推荐.国外程序猿整理的Java资源大全 编程开发 10个强大的纯CSS3动画案例分享 前端project师的神器Sublime Text使用介绍 浅谈SQL语句

疯狂Java学习笔记(84)----------关于 Java 对象序列化您不知道的 5 件事

数年前,当和一个软件团队一起用 Java 语言编写一个应用程序时,我体会到比一般程序员多知道一点关于 Java 对象序列化的知识所带来的好处. 关于本系列 您觉得自己懂 Java 编程?事实上,大多数程序员对于 Java 平台都是浅尝则止,只学习了足以完成手头上任务的知识而已.在本 系列 中,Ted Neward 深入挖掘 Java 平台的核心功能,揭示一些鲜为人知的事实,帮助您解决最棘手的编程挑战. 大约一年前,一个负责管理应用程序所有用户设置的开发人员,决定将用户设置存储在一个 Hashta

疯狂Java学习笔记(84)----------大约 Java 对象序列化,你不知道 5 事

几年前,.当一个软件团队一起用 Java 书面申请.我认识比一般程序猿多知道一点关于 Java 对象序列化的知识所带来的优点. 关于本系列 您认为自己懂 Java 编程?其实,大多数程序猿对于 Java 平台都是浅尝则止,仅仅学习了足以完毕手头上任务的知识而已.在本 系列 中,Ted Neward 深入挖掘 Java 平台的核心功能,揭示一些鲜为人知的事实,帮助您解决最棘手的编程挑战. 大约一年前,一个负责管理应用程序全部用户设置的开发者,决定将用户设置存储在一个 Hashtable中,然后将这

java学习笔记(3):java的工作原理及相关基础

一.运行机制 如上图所示,图中内容即为Java的运行机制: 1.我们一开始所编写的代码文件存储格式为(如text.java)文件,这就是源程序文件 2.在Java编辑器的作用下,也就是就行了编译,形成字节码文件(如text.class)文件,其实,这个Java编译器是我们所说的Java虚拟机,其中,在命令行的处理方式如下: 要在当前文件目录下打开命令行进行编译 3.之后class文件经过类装载器.字节码校验器.解释器的处理,就变成了1010010……的二进制形式了,通过操作系统平台将结果显示在屏

Java学习笔记—第十二章 Java网络编程入门

第十二章  Java网络编程入门 Java提供的三大类网络功能: (1)URL和URLConnection:三大类中最高级的一种,通过URL网络资源表达方式,可以很容易确定网络上数据的位置.利用URL的表示和建立,Java程序可以直接读入网络上所放的数据,或把自己的数据传送到网络的另一端. (2)Socket:又称"套接字",用于描述IP地址和端口(在Internet中,网络中的每台主机都有一个唯一的IP地址,而每台主机又通过提供多个不同端口来提供多种服务).在客户/服务器网络中,当客

java学习笔记(二)基础语法(上)

Java 作为一门编程语言,与其它语言一样,有字符集,标识符和关键字,变量,常量,语句等编程语言的基本要素. 关键字:abstract抽象的,boolean布尔型,break跳出循环,continue中止本次循环,byte字节型,case,catch,char,class,const,default,do,double,else,extends,assert,final,finally,float ,for,if,implements,import,instandceof,int,interfa

Java学习笔记——浅谈数据结构与Java集合框架(第二篇、Queue、Set)

江南好,何处异京华. 香散翠帘多在水,绿残红叶胜于花.无事避风沙. --<纳兰词> 诗词再好,大图不能忘 上大图: 先说说栈和队列: 栈就好比手枪的弹匣,你往里面压入子弹,最先压入的子弹就到了弹匣最底部的位置,最后压入的子弹在弹匣顶部.发射子弹的时候每次将弹匣顶部的子弹弹出发射.无法越过顶部子弹发射下面的子弹. 栈(stack)是限定仅在表尾进行插入和删除操作的线性表,LIFO 队列就跟上学那会儿排队打饭一样,但是不能加塞儿. 队列(queue)是只允许在队列一端进行插入操作,另一端进行删除操

java学习笔记(十五)java网络编程

OSI模型分为七层(从下到上):物理层.数据链路层.网络层.传输层.会话层.表示层.应用层. 不同主机之间的相同层次称为对等层.对等层之间互相通信需要遵守一定的规则,称之为协议,我们将某个主机上运行的某种协议的集合称为协议栈.主机正是利用这个协议栈来接收和发送数据的. TCP/IP模型:网络接口层.网络互连层.传输层.应用层. 在网络编程中需要注意的问题包括: 1.是如何找到网络上的主机上的要进行通讯的程序: 2.是找到了主机上的程序后如何传输数据. 端口号:是一组16位的无符号二进制数,每个端

【Java学习笔记之十三】初探Java面向对象的过程及代码实现

理解Java面向对象的重要知识点: 一. 类,对象 类?首先举一个例子:小李设计了一张汽车设计图,然后交给生产车间来生产汽车,有黑色的.红色的.白色的... 这里,汽车设计图就是我们说的类(class),生产车间就是new构造器(大部分对象都是new出来的),生产出来的汽车就是我们要说的对象.可以说java编程实质就是构建类的过程. 对象?万物皆对象,宇宙中,如植物,动物,人类,每个个体都是各司其职.各尽所能的.这就要求对象高内聚.低耦合(简单理解就是人的大脑,它负责思考,想象,记忆,而不能呼吸