使用Tesseract破解验证码并训练字库的方法

时间:2020-12-10 08:54:36

介绍:Tesseract是一个Google支持的开源的OCR图文识别开源项目,可以较好的识别常见的字体(字母、数字和汉字)并且可以根据需求训练出指定字体的字库,GitHub上有众多开发者贡献的字库。

最近Boss让破解一中类型的验证码,大概长这个样子使用Tesseract破解验证码并训练字库的方法

破解的详细过程下面会慢慢描述,在破解的时候遇到了各种坑,然而总结出来就只有这两点
1、图片不能太小
2、图片不能太脏
满足了这些条件破解成功率基本就能保证在85%以上

首先安装tesseract(需要JDK环境),并下载jTessBoxEditor训练字库工具

一、图片的预处理
处理干净的图片可以提高识别率,对于上面这种干扰点和背景色比较乱的验证码来说是必不可少的一步,我就对上面的图片进行了比较繁琐的处理,最后得到的结果完全就是一个白色的背景和剩下的字母数字,如果需要,可以将图片放大几倍提高正确率;
然后就需要一个比较全的样本文件集合,我将上面的一个验证码切割成了四个独立的图片文件(当然了,一个好的验证码要有随机的扭曲和黏合,字符不能只出现在固定的位置,这种才能称为有效的验证码,否则能被这样切割成独立字符的简直就是对验证码的侮辱)拉取了上千个验证码后就能得到相当丰富的样本集。
在样本中选取一些比较有代表性的字符取组装成一个模版:
1、大写字母:
使用Tesseract破解验证码并训练字库的方法
2、小写字母:
使用Tesseract破解验证码并训练字库的方法
3、数字:
使用Tesseract破解验证码并训练字库的方法

二、训练字库
使用jTessBoxEditor将上面的图片模版合并成一个tif文件:
Tools–>Merger TIFF(使用shift选中多个文件)
然后输入命令行生成box文件
tesseract ybx.font.exp0.tif ybx.font.exp0 batch.nochop makebox
ybx.font.exp0.tif是我tif文件的名称,tif和box名称要保持一致并且要符合以下格式:

tesseract [lang].[fontname].exp[num].tif [lang].[fontname].exp[num] batch.nochop makebox

ybx是字体库的名称,exp0代表版本
tif和box要放在同一路径下,然后使用jTessBoxEditor的Box Editor打开tif:
使用Tesseract破解验证码并训练字库的方法
一定要将对应的图片区域识别的结果进行更正,
将三个模版更正结果后保存即可
在同级目录下新建名为font_properties的文本文件内容为

font 0 0 0 0 0 

然后将以下代码保存成bat文件执行生成字体库文件

rem 执行改批处理前先要目录下创建font_properties文件

echo Run Tesseract for Training..
tesseract.exe ybx.font.exp0.tif ybx.font.exp0 -l eng digits nobatch box.train

echo Compute the Character Set..
unicharset_extractor.exe ybx.font.exp0.box
mftraining -F font_properties -U unicharset -O ybx.unicharset ybx.font.exp0.tr

echo Clustering..
cntraining.exe ybx.font.exp0.tr

echo Rename Files..
rename normproto ybx.normproto
rename inttemp ybx.inttemp
rename pffmtable ybx.pffmtable
rename shapetable ybx.shapetable

echo Create Tessdata..
combine_tessdata.exe ybx.

如果图片太小或者太脏这个批处理文件会得不到正确结果

将生成的ybx.traineddata文件放入tesseract的字体库文件路径下就可以使用了:

tesseract *****.jpg result -l ybx

三、在JAVA程序中的使用
1、pom.xml中加入依赖:

         <dependency>
<groupId>org.bytedeco.javacpp-presets</groupId>
<artifactId>tesseract</artifactId>
<version>3.04-1.1</version>
</dependency>

2、实例化TesseractApiBean

    @Bean
public TessBaseAPI getTessBaseAPI() {
TessBaseAPI api = new TessBaseAPI();
if (api.Init(null, "ybx") != 0) {
System.err.println("Could not initialize tesseract.");
// System.exit(1);
}

return api;
}

3、调用api得到识别结果

    @Autowired
TessBaseAPI api;
/**
* 识别文件返回对应的验证码,只使用tesseract方法
* @param postSrc
* @return
*/

public String getImageCpicByTessBase(String imageFilePath) throws Exception{
if(api == null){
logger.info(" TessBaseAPI is null cannot get code");
return null;
}
BytePointer outText;
PIX image = pixRead(imageFilePath);
api.SetImage(image);
outText = api.GetUTF8Text();
String code = outText.getString();
System.out.println("OCR output:\n" + code);
return code.replace(" ", "").trim();
}

看到那个pixRead方法了吗,哈哈哈。。。。你问我那个是哪个,我才不会告诉你那是我静态导入的

import static org.bytedeco.javacpp.lept.pixRead;

看到lept了吗,这个包是区分平台的,windows上编译好的jar包会引入这两个包:
leptonica-1.72-1.1-windows-x86_64.jar
tesseract-3.04-1.1-windows-x86_64.jar
你要是放到了linux上,那肯定是不行的。需要用到个javacpp像个的东西,不太懂也没过多研究,应该就是通过c或c++调用java的jni接口吧。

好了,如果操作过程中出现各种错误的话,多搜搜吧,百度搜的结果也就*能看,如果翻不了墙,最次也得用bing。真心不想吐槽百度搜技术问题展示的乱七八糟的结果