因为工作中需要自动的识别验证码,起初,我们采用市面上的打码服务,可是随着量越来越大,打码服务给我们带来了很大的成本。经过观察,有很大一部分的验证码还是比较简单的,因此我们准备自己研发一个验证码识别服务,用来识别简单的验证码。
经过本人调研(其实就是google一顿乱搜^_^),发现了Tesseract-OCR,简单的介绍下它吧:
Tesseract是一个开源的OCR(Optical Character Recognition,光学字符识别)引擎,可以识别多种格式的图像文件并将其转换成文本,目前已支持60多种语言(包括中文)。 Tesseract最初由HP公司开发,后来由Google维护,github地址: https://github.com/tesseract-ocr/tesseract。
OK,让我们开始吧,本文使用的环境是Centos7。
Tesseract识别图像上文本的时候,需要基于一定的语言库,我们既可以使用默认的语言库,也可以自己来定制语言库。
以下是搭建服务的步骤,记录下来作为备份。
首先我们来体验下默认的语言库,我们先安装下环境:
1
2
3
4
5
6
7
|
$
sudo
yum
install
leptonica
leptonica
-
devel
tesseract
tesseract
-
devel
-
y
$
tesseract
-
v
tesseract
3.04.00
leptonica
-
1.72
libgif
4.1.6
(
?
)
:
libjpeg
6b
(
libjpeg
-
turbo
1.2.1
)
:
libpng
1.2.49
:
libtiff
3.9.4
:
zlib
1.2.3
:
libwebp
0.4.3
|
我们测试2张验证码图片,如下:
1、LXDT.jpg
我们执行以下命令,并查看结果:
1
2
3
4
5
6
|
$
tesseract
LXDT
.jpg
LXDT
-
l
eng
Tesseract
Open
Source
OCR
Engine
v3
.
04.00
with
Leptonica
$
cat
LXDT
.txt
LXDT
|
2、NG8N.jpg
我们执行以下命令,并查看结果:
1
2
3
4
5
6
|
$
tesseract
NG8N
.jpg
NG8N
-
l
eng
Tesseract
Open
Source
OCR
Engine
v3
.
02.02
with
Leptonica
$
cat
NG8N
.txt
NGsN
|
在上面的操作中,我们使用tesseract来识别LXDT.jpg图片,并将结果输出到LXDT(.txt后缀会自动添加)文件中,在这里,我们使用的语言库是默认的英文库eng,从结果(LXDT.txt文件中的内容)可以看出,tesseract正确的识别了LXDT验证码。
同样的步骤,tesseract 将NG8N.jpg识别为了NGsN,本人随机的挑选了20张类似的验证码,使用tesseract默认的语言库eng,正确的识别了其中的15张,也就是说成功率为75%,可以说是一个不错的结果了,毕竟默人的eng语言库识别的是比较标准的字体。但是对于一个线上的服务来说,75%是不够的,因此我们就需要自己来制作语言库。
在最近几年,机器学习是比较热门的技术,其实自制语言库,然后让tesseract使用我们自己的语言库就是机器学习的一个应用(其实本人也只是一个门外汉,大学的时候做数学建模的时候接触过一些^_^)。
OK,让我们开始训练样本数据吧!
1、准备样本数据
首先我们需要准备一批样本数据用于训练,在这里,本人准备了530张不同的验证码。如下示例:
2、编译安装tesseract-ocr
在训练数据之前,我们需要手工编译安装tesseract-ocr以及它的训练工具,否则运行过程中会报错….当然,只需要在自制语言库的时候编译安装,线上的服务使用yum安装即可。
本人从 https://code.google.com/p/tesseract-ocr/downloads/list 下载 tesseract-ocr-3.02.grc.tar.gz文件,然后进行安装,输入的命令依次为(省略输出):
1
2
3
4
5
6
7
8
9
|
$
sudo
.
/
autogen
.sh
$
sudo
.
/
configure
--
prefix
=
/
usr
$
sudo
make
$
sudo
make
install
$
cd
training
/
$
sudo
make
$
sudo
make
install
|
3、下载jTessBoxEditor
我们需要使用jTessBoxEditor对样本数据的识别结果进行校正,它的下载地址是:http://sourceforge.net/projects/vietocr/files/jTessBoxEditor/。此处本人下载的是 jTessBoxEditor-1.4-src.zip,解压后,我们执行其中的jar包即可得到图形界面:
1
2
3
|
$
sudo
java
-
Xms128m
-
Xmx1024m
-
jar
jTessBoxEditor
/
jTessBoxEditor
.jar
|
图形界面:
4、验证码图片格式转换为.tiff
因为jTessBoxEditor只能处理.tiff后缀的文件,因此我们需要将验证码图片转化为.tiff后缀,这里我们使用ImageMagick的convert工具进行转化,首先安装ImageMagick:
1
2
3
4
5
6
7
|
$
sudo
yum
install
ImageMagick
$
convert
--
version
Version
:
ImageMagick
6.7.8
-
9
2014
-
06
-
10
Q16
http
:
/
/
www
.imagemagick
.org
Copyright
:
Copyright
(
C
)
1999
-
2012
ImageMagick
Studio
LLC
Features
:
OpenMP
|
然后我们通过shell脚本批量转换当前目录下的图片:
1
2
3
4
5
6
7
8
|
#!/bin/sh
for
file
in
`
ls
*
.jpg
`
do
name
=
$
{
file
%
.
*
}
convert
$file
$name
".tiff"
done
|
这样我们便得到了一批.tiff后缀结尾的验证码。
当然,我们也可以使用ImageMagick的mogrify工具进行批量转换:
1
2
3
|
$
mogrify
-
path
.
/
TIFF
/
-
format
tiff
*
.jpg
|
其中-path选项指定了tiff文件的存放路径。
5、将.tiff后缀的验证码图片合并成 .tif文件
这里我们需要第3步下载的jTessBoxEditor,我们通过界面上的Tools/Merge TIFF 将之前生成的 .tiff文件合并成一个eng.wchao.exp0.tif文件:
按住shift选择多个图片,输入保存的文件名(eng.wchao.exp0.tif)后点击保存即可:
其中tif文件的命名格式为:[lang].[fontname].exp[num].tif,注意这个格式是Tesseract官网定义的,如果不按照这个格式来定义,比如定义为wchao.tif,那么生成的语言库不会生效-_-。
6、生成.box 文件
1
2
3
4
5
|
$
sudo
tesseract
eng
.wchao
.exp0
.tif
eng
.wchao
.exp0
batch
.nochop
makebox
$
ls
*
wchao
*
eng
.wchao
.exp0
.box
eng
.wchao
.exp0
.tif
|
box文件的命名规范与tif命名规范一致。
7、使用jTessBoxEditor校正字符
使用上图中的open打开刚才合并的eng.wchao.exp0.tif文件,这时,我们就可以校正Tesseract的识别结果了,我们可以使用工具栏上的merge和split对识别的结果进行合并和拆分,通过翻页来查看下一张验证码。
当我们校正完所有的验证码之后,点击界面上的save保存即可。
经过对样本数据的人工校正之后,我们就可以生成语言库了。
1、生成字符特征文件
1
2
3
|
$
sudo
tesseract
eng
.wchao
.exp0
.tif
eng
.wchao
.exp0
nobatch
box
.train
|
2、产生字符集
1
2
3
|
sudo
unicharset_extractor
eng
.wchao
.exp0
.box
|
3、定义字体特征文件 font_properties
在font_properties文件中写入wchao 0 0 0 0 0 即可,表示字体名为wchao,是普通字体,不加粗,不倾斜。
4、生成shapetable
1
2
3
|
$
sudo
shapeclustering
-
F
font_properties
-
U
unicharset
eng
.wchao
.exp0
.tr
|
5、聚集字符特征
1
2
3
|
$
sudo
mftraining
-
F
font_properties
-
U
unicharset
eng
.wchao
.exp0
.tr
|
6、生成字符形状正常变化特征文件normproto
1
2
3
|
$
sudo
cntraining
eng
.wchao
.exp0
.tr
|
至此,我们得到了以下的文件:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
|
$
tree
.
├──
eng
.wchao
.exp0
.box
├──
eng
.wchao
.exp0
.tif
├──
eng
.wchao
.exp0
.tr
├──
eng
.wchao
.exp0
.txt
├──
font
_properties
├──
inttemp
├──
normproto
├──
pffmtable
├──
shapetable
└──
unicharset
|
7、给inttemp,normproto,pffmtable,shapetable,unicharset 添加前缀 “wchao.”,也就是我们的字体名。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
|
$
tree
.
├──
eng
.wchao
.exp0
.box
├──
eng
.wchao
.exp0
.tif
├──
eng
.wchao
.exp0
.tr
├──
eng
.wchao
.exp0
.txt
├──
font
_properties
├──
wchao
.inttemp
├──
wchao
.normproto
├──
wchao
.pffmtable
├──
wchao
.shapetable
└──
wchao
.unicharset
|
8、生成语言库
注意命令中写的是 wchao. 就是有个”.”。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
|
$
sudo
combine_tessdata
wchao
.
Combining
tessdata
files
TessdataManager
combined
tesseract
data
files
.
Offset
for
type
0
is
-
1
Offset
for
type
1
is
140
Offset
for
type
2
is
-
1
Offset
for
type
3
is
5248
Offset
for
type
4
is
374421
Offset
for
type
5
is
374959
Offset
for
type
6
is
-
1
Offset
for
type
7
is
-
1
Offset
for
type
8
is
-
1
Offset
for
type
9
is
-
1
Offset
for
type
10
is
-
1
Offset
for
type
11
is
-
1
Offset
for
type
12
is
-
1
Offset
for
type
13
is
404869
Offset
for
type
14
is
-
1
Offset
for
type
15
is
-
1
Offset
for
type
16
is
-
1
|
至此,我们便生成了需要的 wchao.traineddata 文件,我们将这个文件拷贝到tessdata目录下(yum安装时的目录为:/usr/share/tesseract/tessdata/ 上述编译安装时目录为: /usr/share/tessdata/)即可使用。
9、使用新的语言库来识别验证码
1
2
3
4
5
6
|
$
tesseract
NG8N
.jpg
NG8N
-
l
wchao
Tesseract
Open
Source
OCR
Engine
v3
.
02.02
with
Leptonica
[
wangchao7
@
localhost
images
]
$
cat
NG8N
.txt
NG8N
|
从上面的结果可以看出,新的语言库可以正确的识别NG8N.jpg 验证码,经过测试,本人又取了一批和样本数据类似的验证码,识别的成功率在90% ~ 95%,而且识别一张上面的验证码大概在30ms左右,基本已经可以作为线上服务使用了^_^