今天想着把以前做过的一个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"); 回车换行的字符串表示

【Java程序】tesseract_orc java上的一种实现方法的更多相关文章

  1. 我的第一个Java程序和Java简介

    public calss HelloWorld{ public static void main(String[] args){ System.out.println("Hello Worl ...

  2. 执行Asp.net应用程序在Linux上的3种托管方式

    执行Asp.net应用程序在Linux上的3种托管方式 想要执行Asp.net应用程序在Linux上.我们有3种选择: 1.使用Apache作为Webserver.使用mod_mono:http:// ...

  3. Java 微信公众号上传永久素材的方法

    Java 微信公众号上传永久素材的方法 学习了:http://blog.csdn.net/u013791374/article/details/53258275 膜拜一下,源码如下: @Request ...

  4. redis(Springboot中封装整合redis,java程序如何操作redis的5种基本数据类型)

    平常测试redis操作命令,可能用的是cmd窗口 操作redis,记录一下 java程序操作reids, 操作redis的方法 可以用Jedis ,在springboot 提供了两种 方法操作 Red ...

  5. 将Java程序作成exe文件的几种方法【转载】

    看到网上有同志的介绍将Java程序作成exe文件的方法,写的不错,但是也许是这篇文章完成的时间比较早,许多内容已经不合适了.我在这里补充几条: 一.exe4j 说明:exe4j可以将Jar文件制作成e ...

  6. java 程序从linux 上接收不可见字符

    近期在写一个简单的小java程序,希望在运行java 程序时,从shell 中接收参数,并且参数的内容为不可见字符. 开始时还觉得可以使用"\"之类的转义符来写,后来发现java程 ...

  7. java程序在一个电脑上只启动一次,只开一个进程

    方案1: 单进程程序可以用端口绑定.程序启动的时候可以尝试看该端口是否已经被占用,如果占用则程序已经启动. 方案2:你可以在java程序中创建一个隐藏文件,程序退出的时候删除这个文件.这样在程序启动的 ...

  8. 第一个java程序以及java的运行机制

    课堂要点: 编写第一个java程序以及理解java的运行机制. 1.基本命令介绍: javac命令: 编译java文件得到.class字节码文件 -encoding 参数:指定编译的编码 java命令 ...

  9. Java程序在Linux上运行虚拟内存耗用很大

    突然集群的2个节点挂了,通过top查看, 虚拟内存22G, 通过 pmap -x 8 | grep anon 一大堆64M Linux下glibc的内存管理机制用了一个很奇妙的东西,叫arena.在g ...

随机推荐

  1. 异常 Cannot resolve class or package

    spring boot yml配置异常Cannot resolve class or package 是因为mvaen设置 pom.xml的文件配置如上,scope 范围指定为runtime,runt ...

  2. Uva10491 Cows and Cars 【迁移自洛谷博客】

    题目大意 假设有a头牛,b辆车(门的总数为a+b),你先选一个门,然后你最终选择前主持人会替你打开C扇有牛的门(不会打开你已经选择的门),问你要不要换门,输出"总是换门"的策略下, ...

  3. bzoj 1001 原图最小割转化为对偶图最短路

    题目大意: 现在小朋友们最喜欢的"喜羊羊与灰太狼",话说灰太狼抓羊不到,但抓兔子还是比较在行的, 而且现在的兔子还比较笨,它们只有两个窝,现在你做为狼王,面对下面这样一个网格的地形 ...

  4. github ssh秘钥配置

    1.本地生产ssh密钥对 ssh-keygen -t rsa -C "your_email@example.com" 2. 进入~/.ssh 拷贝公钥进入github里面

  5. 输出匹配项:grep

    命令格式: grep pattern [file...] When grep encounters a "pattern" in the file, it prints out t ...

  6. vue 全局 js 方法

    1.新增 getCurrentDataType.js 文件 import cookieUtils from '@/config/cookieUtils' function getCurrentData ...

  7. 【leetcode】472. Concatenated Words

    题目如下: Given a list of words (without duplicates), please write a program that returns all concatenat ...

  8. 验证码生成(servlet)

    一 效果如下: 二 java 代码如下: import java.awt.Color; import java.awt.Font; import java.awt.Graphics; import j ...

  9. wamp环境的搭建

    本文详细介绍了在Windows2003下使用Apache2.2.21/PHP5.3.5/Mysql5.5.19/phpMyAdmin3.4.9搭建php开发环境. 第一步:下载安装的文件 1. Apa ...

  10. centos6.8下安装nginx

    我用的阿里云上的镜像,make的时候总是出错,后来说是gcc安装不完整,要重新用下面命令安装 下: yum install gcc gcc-c++ gcc-g77 接下来下载nginx用到的一些库 w ...