Tesseract做图片验证码识别
linux下的安装参考这里
转载请标明出处:https://www.jianshu.com/p/c9cd23ea84fa
环境准备
yum -y update
yum -y install libstdc++ autoconf automake libtool autoconf-archive pkg-config gcc gcc-c++ make libjpeg-devel libpng-devel libtiff-devel zlib-devel
安装leptonica这里下载
tar -zvxf leptonica-1.74.4.tar.gz
cd leptonica-1.74.4
./autobuild
./configure
make
make install
安装tesseract这里下载
unzip tesseract-master.zip
cd tesseract-master
(1)./autogen.sh
(2)PKG_CONFIG_PATH=/usr/local/lib/pkgconfig LIBLEPT_HEADERSDIR=/usr/local/include ./configure –with-extra-includes=/usr/local/include –with-extra-libraries=/usr/local/lib
(3)LDFLAGS=”-L/usr/local/lib” CFLAGS=”-I/usr/local/include” make
(4)make install
下载数据这里下载
cd /usr/local/share/
上传eng.traineddata
到此就安装完成了。
Windows下的安装
windows上的安装就不介绍了,注意安装好了以后要添加环境变量:
(1)path中添加:D:\Program Files (x86)\Tesseract-OCR\tessdata
(2)新建TESSDATA_PREFIX:D:\Program Files (x86)\Tesseract-OCR\tessdata
使用
tesseract image1.jpg out –psm 7 -l eng
image1.jpg:是输入文件名
out:识别出来的文字存放在out.txt这个文件中
-l:代表文字的类型,eng就是英文。
–psm:代表不同的切割方式
- 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.
- 11 Sparse text. Find as much text as possible in no particular order.
- 12 Sparse text with OSD.
- 13 Raw line. Treat the image as a single text line, bypassing hacks that are Tesseract-specific.
为了提高识别率可以做灰度化二值化等处理.
JAVA代码如下
public class OCRUtil {
private static final String EOL = System.getProperty("line.separator");
public static String recognizeText(byte[] image) throws Exception {
//图片预处理,灰度化+二值化
image = preHandleImage(image);
//把字节数组保存到临时目录
String tempDir=System.getProperty("java.io.tmpdir");
String uuid = UUIDUtil.uuid();
String tempFileName = uuid +".jpg";
String resultFileName = uuid;
File tempFile = new File(tempDir, tempFileName);
File resultFile = new File(tempDir, resultFileName);
IOUtil.saveInputStream(new ByteArrayInputStream(image), new FileOutputStream(tempFile));
//生成操作系统命令
List<String> cmd = new ArrayList<String>();
if(OSUtil.isUnixLikeSystem()) {
cmd.add("tesseract");
}else {
cmd.add("cmd");
cmd.add("/c");
cmd.add("tesseract.exe");
}
cmd.add(tempFile.getAbsolutePath());
cmd.add(resultFile.getAbsolutePath());
cmd.add("-l");
cmd.add("eng");
cmd.add("--psm");
cmd.add("7");
FileInputStream fin = null;
BufferedReader in = null;
try {
//调用操作系統命令
StringBuffer sb = new StringBuffer();
ProcessBuilder pb = new ProcessBuilder();
pb.directory(new File(tempDir));
pb.command(cmd);
pb.redirectErrorStream(true);
Process process = pb.start();
int w = process.waitFor();
if (w == 0){// 0代表正常退出
fin = new FileInputStream(resultFile.getAbsolutePath() + ".txt");
in = new BufferedReader(new InputStreamReader(fin, "UTF-8"));
String str = null;
while ((str = in.readLine()) != null) {
sb.append(str).append(EOL);
}
return sb.toString().replaceAll("(?is)\\s+", "");
} 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);
}
}finally {
IOUtil.close(in,fin);
if(tempFile != null) {
tempFile.delete();
}
if(resultFile != null) {
resultFile.delete();
File file = new File(resultFile.getAbsolutePath()+".txt");
if(file!=null && file.exists()) {
file.delete();
}
}
}
}
public static byte[] preHandleImage(byte[] imgBytes) throws IOException {
if(imgBytes == null) {
return null;
}
BufferedImage bufferedImage = ImageIO.read(new ByteArrayInputStream(imgBytes));
int h = bufferedImage.getHeight();
int w = bufferedImage.getWidth();
// 灰度化
int[][] gray = new int[w][h];
for (int x = 0; x < w; x++) {
for (int y = 0; y < h; y++) {
int argb = bufferedImage.getRGB(x, y);
// 图像加亮(调整亮度识别率非常高)
int r = (int) (((argb >> 16) & 0xFF) * 1.1 + 30);
int g = (int) (((argb >> 8) & 0xFF) * 1.1 + 30);
int b = (int) (((argb >> 0) & 0xFF) * 1.1 + 30);
if (r >= 255) {
r = 255;
}
if (g >= 255) {
g = 255;
}
if (b >= 255) {
b = 255;
}
gray[x][y] = (int) Math.pow(
(Math.pow(r, 2.2) * 0.2973 + Math.pow(g, 2.2) * 0.6274 + Math.pow(b, 2.2) * 0.0753), 1 / 2.2);
}
}
// 二值化
int threshold = ostu(gray, w, h);
BufferedImage binaryBufferedImage = new BufferedImage(w, h, BufferedImage.TYPE_BYTE_BINARY);
for (int x = 0; x < w; x++) {
for (int y = 0; y < h; y++) {
if (gray[x][y] > threshold) {
gray[x][y] |= 0x00FFFF;
} else {
gray[x][y] &= 0xFF0000;
}
binaryBufferedImage.setRGB(x, y, gray[x][y]);
}
}
ByteArrayOutputStream out = new ByteArrayOutputStream();
ImageIO.write(binaryBufferedImage, "jpg", out);
out.close();
return out.toByteArray();
}
private static int ostu(int[][] gray, int w, int h) {
int[] histData = new int[w * h];
// Calculate histogram
for (int x = 0; x < w; x++) {
for (int y = 0; y < h; y++) {
int red = 0xFF & gray[x][y];
histData[red]++;
}
}
// Total number of pixels
int total = w * h;
float sum = 0;
for (int t = 0; t < 256; t++)sum += t * histData[t];
float sumB = 0;
int wB = 0;
int wF = 0;
float varMax = 0;
int threshold = 0;
for (int t = 0; t < 256; t++) {
wB += histData[t]; // Weight Background
if (wB == 0) continue;
wF = total - wB; // Weight Foreground
if (wF == 0) break;
sumB += (float) (t * histData[t]);
float mB = sumB / wB; // Mean Background
float mF = (sum - sumB) / wF; // Mean Foreground
// Calculate Between Class Variance
float varBetween = (float) wB * (float) wF * (mB - mF) * (mB - mF);
// Check if new maximum found
if (varBetween > varMax) {
varMax = varBetween;
threshold = t;
}
}
return threshold;
}
}