摘要
Java + OCR 提取图片文字。在电商平台中,平台可能需要对商家一些营业执照,身份证件件进行审核,我们可能需要证件中的编号进行提取。当少量商家的时候,可以人工审核,把证件中的编号提取出来;当商家数量变多的时候,平台审核就很耗费人工。这个时候我们就自然而然想到能不能把图片中的文字提取出来。下面我们就来了解一下OCR图片文字提取。SpringBoot实战电商项目mall4j 地址 : [https://gitee.com/gz-yami/mall4j]
Java+Tesseract_OCR 图片文字提取初次入门
可以调用第三放接口,进行图片文字提取,例如:百度API这里我们自己在本地来做一个图片文字提取,使用Java+Tesseract的方式
环境准备
win10,jdk1.8, idea,maven
下载tesseract3.02,中文词库
首先必须要有Java环境JDK
1.下载安装tesseract3.02
2.下载中文词库chi_sim.traineddata
百度网盘:
链接:https://pan.baidu.com/s/1VYx6...
提取码:hsr7
3.将chi_sim.traineddata放在tessdata目录下
4.打开\tessdata\configs目录下的digits文件,将
tessedit_char_whitelist 0123456789-. 改为 tessedit_char_whitelist 0123456789x.
5.配置环境变量(tesseract3.02的安装目录)
6.测试是否安装完成
WIN+R打开cmd命令输入tesseract
出现表示安装完成
Usage:tesseract imagename outputbase [-l lang] [-psm pagesegmode] [configfile...]
pagesegmode values are:
0 = Orientation and script detection (OSD) only.
1 = Automatic page segmentation with OSD.
2 = Automatic page segmentation, but no OSD, or OCR
3 = Fully automatic page segmentation, but no OSD. (Default)
4 = Assume a single column of text of variable sizes.
5 = Assume a single uniform block of vertically aligned text.
6 = Assume a single uniform block of text.
7 = Treat the image as a single text line.
8 = Treat the image as a single word.
9 = Treat the image as a single word in a circle.
10 = Treat the image as a single character.
-l lang and/or -psm pagesegmode must occur before anyconfigfile.
Single options:
-v --version: version info
--list-langs: list available languages for tesseract engine
提取文字
tesseract C:/pic/1.png C:/pic/1 -l chi_simc盘的图片,生成1.txt(提取到的文字内容)
-l :不是1 是英文字母L对应的小写字母l
chi_sim 中文词库
java 项目中导入依赖
<dependency>
<groupId>net.sourceforge.tess4j</groupId>
<artifactId>tess4j</artifactId>
<version>3.2.1</version>
<exclusions>
<exclusion>
<groupId>com.sun.jna</groupId>
<artifactId>jna</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>net.java.dev.jna</groupId>
<artifactId>jna</artifactId>
<version>4.1.0</version>
</dependency>
<!-- https://mvnrepository.com/artifact/javax.media/jai_imageio -->
<dependency>
<groupId>javax.media</groupId>
<artifactId>jai_imageio</artifactId>
<version>1.1.1</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.swinglabs/swingx -->
<dependency>
<groupId>org.swinglabs</groupId>
<artifactId>swingx</artifactId>
<version>1.6.1</version>
</dependency>
代码
ImageIOHelper.class
package com.example.excel.excelexportodb.Utils;
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.github.jaiimageio.plugins.tiff.TIFFImageWriteParam;
//import com.sun.media.imageio.plugins.tiff.TIFFImageWriteParam;
/**
* 类说明 :创建临时图片文件防止损坏初始文件
*/
public class ImageIOHelper {
//设置语言
private Locale locale=Locale.CHINESE;
//自定义语言构造的方法
public ImageIOHelper(Locale locale){
this.locale=locale;
}
//默认构造器Locale.CHINESE
public ImageIOHelper(){
}
/**
* 创建临时图片文件防止损坏初始文件
* @param imageFile
* @param imageFormat like png,jps .etc
* @return TempFile of Image
*/
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();
//设置writeParam
TIFFImageWriteParam tiffWriteParam = new TIFFImageWriteParam(Locale.CHINESE);
tiffWriteParam.setCompressionMode(ImageWriteParam.MODE_DISABLED);
//设置可否压缩
//获得tiffWriter和设置output
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;
}
/**
* 给tempfile添加后缀
* @param imageFile
* @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());
}
}
OCRUtil.class
package com.example.excel.excelexportodb.Utils;
import java.io.*;
import java.util.ArrayList;
import java.util.List;
import java.util.Locale;
import org.jdesktop.swingx.util.OS;
/**
* 类说明:OCR工具类
*/
public class OCRUtil {
private final String LANG_OPTION = "-l";
//英文字母小写l,并非阿拉伯数字1
private final String EOL = System.getProperty("line.separator");
/**
* ocr的安装路径
*/
private String tessPath = "D://tess4j//tess4j-src//tesseract-ocr-set-3.0//Tesseract-OCR";
public OCRUtil(String tessPath,String transFileName){
this.tessPath=tessPath;
}
//OCRUtil的构造方法,默认路径是"C://Program Files (x86)//Tesseract-OCR"
public OCRUtil(){ }
public String getTessPath() {
return tessPath;
}
public void setTessPath(String tessPath) {
this.tessPath = tessPath;
}
public String getLANG_OPTION() {
return LANG_OPTION;
}
public String getEOL() {
return EOL;
}
/**
* @return 识别后的文字
*/
public String recognizeText(File imageFile,String imageFormat)throws Exception{
File tempImage = new ImageIOHelper().createImage(imageFile,imageFormat);
return ocrImages(tempImage, imageFile);
}
/**
* 可以自定义语言
*/
public String recognizeText(File imageFile,String imageFormat,Locale locale)throws Exception{
File tempImage = new ImageIOHelper(locale).createImage(imageFile,imageFormat);
return ocrImages(tempImage, imageFile);
}
/**
* @param
* @param
* @return 识别后的内容
* @throws IOException
* @throws InterruptedException
*/
private String ocrImages(File tempImage,File imageFile) throws IOException, InterruptedException{
//设置输出文件的保存的文件目录,以及文件名
File outputFile = new File(imageFile.getParentFile(),"test");
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("chi_sim");
//常用数学公式包
cmd.add("equ");
//英语包
cmd.add("eng");
//创建操作系统进程
ProcessBuilder pb = new ProcessBuilder();
//设置此进程生成器的工作目录
pb.directory(imageFile.getParentFile());
cmd.set(1, tempImage.getName());
//设置要执行的cmd命令
pb.command(cmd);
//设置后续子进程生成的错误输出都将与标准输出合并
pb.redirectErrorStream(true);
long startTime = System.currentTimeMillis();
System.out.println("开始时间:" + startTime);
//开始执行,并返回进程实例
Process process = pb.start();
//最终执行命令为:tesseract 1.png test -l chi_sim+equ+eng
// 输入输出流优化
// printMessage(process.getInputStream());
// printMessage(process.getErrorStream());
int w = process.waitFor();
//删除临时正在工作文件
tempImage.delete();
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();
long endTime = System.currentTimeMillis();
System.out.println("结束时间:" + endTime);
System.out.println("耗时:" + (endTime - startTime) + "毫秒");
}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().replaceAll("\\s*", "");
}
// public static void main(String[] args) throws IOException, InterruptedException {
// String cmd = "cmd /c dir c:\\windows";
// final Process process = Runtime.getRuntime().exec(cmd);
// printMessage(process.getInputStream());
// printMessage(process.getErrorStream());
// int value = process.waitFor();
// System.out.println(value);
// }
private static void printMessage(final InputStream input) {
new Thread(new Runnable() {
@Override
public void run() {
Reader reader = new InputStreamReader(input);
BufferedReader bf = new BufferedReader(reader);
String line = null;
try {
while ((line = bf.readLine()) != null) {
System.out.println(line);
}
} catch (IOException e) {
e.printStackTrace();
}
}
}).start();
}
}
主函数
public static void main(String[] args) throws TesseractException {
String path = "D://1.png";
System.out.println("ORC Test Begin......");
try {
String valCode = new OCRUtil().recognizeText(new File(path), "png");
System.out.println(valCode);
} catch (IOException e) {
e.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
}
System.out.println("ORC Test End......");
}
识别图片
ORC Test Begin......测试123
ORC Test End......
最终识别效果一般,一些复杂文字识别出现乱码,这个时候就需要我们去训练词库了
训练越多就识别的越精确
SpringBoot实战电商项目mall4j 地址 : [https://gitee.com/gz-yami/mall4j]
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。