python 破解验证码之三:用自己训练的数据跑tesseract识别验证码,最后附上正确率

@TOC

用自己训练的数据跑tesseract识别验证码,最后附上正确率

1、使用现成的工具jTessBoxEditor,和tesseract,都是已经写好的工具,不需要再造轮子(尤其是从头学深度学习让你造一个神经网络写完就已经半年后了,还不排除从入门到放弃)首先要安装JDK,训练数据的机器依赖JAVA环境

JDK8:http://www.oracle.com/technetwork/java/javase/downloads/jdk8-downloads-2133151.html

jTessBoxEditor:https://sourceforge.net/projects/vietocr/files/jTessBoxEditor/

2、准备训练数据
我已经写好了代码,简单写了写,都是想着自己用的,所以看起来很小白啦

from PIL import Image
from PIL import ImageDraw
from PIL import ImageFont
import random

def getRandomColor():
    # 获取一个随机颜色(r,g,b)格式的
    c1 = random.randint(0, 255)
    c2 = random.randint(0, 255)
    c3 = random.randint(0, 255)
    return (c1, c2, c3)

def getRandomStr():
    # 获取一个随机字符串 颜色随机
    # 数字
    random_num = str(random.randint(0, 9))
    # 大写
    random_low_alpha = chr(random.randint(97, 122))
    # 小写
    random_upper_alpha = chr(random.randint(65, 90))
    random_char = random.choice([random_num, random_low_alpha, random_upper_alpha])
    return random_char

def getCaptcha_1():
    for pages in range(0, 100):
        # 获取数字验证码 随机颜色
        # 获取一个Image对象,参数分别市RBG模式 宽15030 随机颜色
        captcha = Image.new('RGB', (150, 40), getRandomColor())
        draw = ImageDraw.Draw(captcha)
        # 获取一个font字体对象参数市ttf的字体文件的目录以及字体的大小
        font = ImageFont.truetype("arial.ttf", size=32)
        # 在图片上写东西,参数是:定位,字符串,颜色,字体
        for i in range(4):
            draw.text((20+i*30, 0), str(random.randint(0, 9)), getRandomColor(), font=font)
        captcha.save(open('{}.png'.format(pages), 'wb'), 'png')
        # return captcha
        # captcha.show()

def getCaptcha_2():
    # 固定字符串 随机颜色
    # 获取一个Image对象,参数分别市RBG模式 宽15030 随机颜色
    captcha = Image.new('RGB', (150, 40), getRandomColor())
    # 获取一个画笔对象,将图片传过去
    draw = ImageDraw.Draw(captcha)
    # 获取一个font字体对象参数市ttf的字体文件的目录以及字体的大小
    font = ImageFont.truetype("arial.ttf", size=32)
    # 在图片上写东西,参数是:定位,字符串,颜色,字体
    draw.text((20, 0), 'abcd', getRandomColor(), font=font)
    # captcha.save(open('test.png', 'wb'), 'png')
    # captcha.show()
    return captcha

def getCaptcha_3():
    for pages in range(0, 100):
        # 随机字符串 随机颜色
        captcha = Image.new('RGB', (150, 40), getRandomColor())
        draw = ImageDraw.Draw(captcha)
        font = ImageFont.truetype("arial.ttf", size=32)
        for i in range(4):
            # 循环4次 获得4个随机字符串
            random_char = getRandomStr()
            # 在图片上一次写入得到的随机字符串, 参数是定位 字符串 颜色 字体
            draw.text((20+i*30, 0), random_char, getRandomColor(), font=font)
        captcha.save(open('D:\\Python Workspaces\\constractionMarket\\new_data\\{}.png'.format(pages), 'wb'), 'png')
        # captcha.show()
        # return captcha

def getCaptcha_4():
    # 带有噪点的验证码图片
    captcha = Image.new('RGB', (150, 40), getRandomColor())
    draw = ImageDraw.Draw(captcha)
    font = ImageFont.truetype("arial.ttf", size=32)
    for i in range(4):
        random_char = getRandomStr()
        draw.text((20+i*30, 0), random_char, getRandomColor(), font=font)
    # 噪点噪线
    width = 150
    height = 30
    # 划线
    for i in range(2):
        x1 = random.randint(0, width)
        x2 = random.randint(0, width)
        y1 = random.randint(0, height)
        y2 = random.randint(0, height)
        draw.line((x1, y1, x2, y2), fill=getRandomColor())
    # 划点
    for i in range(15):
        draw.point([random.randint(0, width), random.randint(0, height)], fill=getRandomColor())
        x = random.randint(0, width)
        y = random.randint(0, height)
        draw.arc((x, y, x+4, y+4), 0, 90, fill=getRandomColor())
    # captcha.save(open('test.png', 'wb'), 'png')
    # captcha.show()
    return captcha

我用的是第三个,getCaptcha3,生成的是随机颜色的混合大小写和数字的,比较有当今验证码的代表性(加噪点噪线的太麻烦了,最后的成功率也一定不客观hhh)生成了一百个训练数据(大家千万不要跟我一样沙雕搞那么多训练数据,对于初学的话生成20个左右,熟悉步骤就好了,不然矫正数据的时候真的是眼睛都给我看瞎了)
python 破解验证码之三:用自己训练的数据跑tesseract识别验证码,最后附上正确率_第1张图片
大概就是这个样子
3、打开jTessBoxEditor生成训练样本的合并tif图:
在Tools里的merge TIFF
python 破解验证码之三:用自己训练的数据跑tesseract识别验证码,最后附上正确率_第2张图片
可以按住crtl然后依次点击全部选完你想要放入的训练数据

然后点打开,然后会弹出让你保存,命名规则为
[lang].[fontname].exp[num].tif lang就是他是什么语言,我写的是num_eng,fontname是字体,我的生成验证码地方的字体是arial,大家的计算机应该都是自带我这个的,查询自己电脑有啥字体可以百度,也可以选择字体奇怪一点的增加难度,num是数字,第一次就是0,之后可以1234,我最后的命名是num_eng.arial.exp0.tif 一定要记住你给他的名字,后面要多次用到,记错了就会失败从新来了。
4、tesseract生成box文件
cmd进入在你生成tif文件的地方,输入

tesseract num_eng.arial.exp0.tif num_eng.arial.exp0 -l eng -psm 7 batch.nochop makebox

python 破解验证码之三:用自己训练的数据跑tesseract识别验证码,最后附上正确率_第3张图片
类似于我上面这样的报错不用管
5、用jTessBoxEditor矫正.box文件的错误
.box文件记录了他自动识别出的内容,训练前用jtessboxeditor调整纠正,打开jTessBoxEditor点击Box Editor—>Open,打开之前生成的tif文件,会自动关联.box文件(两文件要在同一个目录下)
python 破解验证码之三:用自己训练的数据跑tesseract识别验证码,最后附上正确率_第4张图片
x,y对应x轴y轴,width,height是宽高
右上角可以调整框的位置,把它包住字符并在char里查看是否跟图的一致,跟我一样眼瞎的可以点击Box View 查看大图,这一步你就知道为什么叫你们少生成点训练数据了!
如果识别少了的,可以点击insert插入一个新框,或者多了的点delete。你有可能会遇到一个字都没有识别到,然后还不允许你插入,因为box必须在一个box后面,一个box都没有就不能插入,这样的情况用notepad打开,记事本应该也可以,打开tif文件,会看到一排排的数据像这样的
python 破解验证码之三:用自己训练的数据跑tesseract识别验证码,最后附上正确率_第5张图片
如果你遇到有的数据都没有,比如是第三页 那么肯定在图的位置第几页里就没有那里的数据,比如是第二页一个字符都没有识别出来,就会是这样的

5 21 11 3 34 0
X 12 13 14 15 0
a 1 1 1 1 0
b 15 16 4 4 0
c 15 15 15 15 2
1 54 54 54 54 2
1 51 51 51 51 2
s 51 51 51 51 2

这是我瞎打的 瞎看看就行
你把他改成

5 21 11 3 34 0
X 12 13 14 15 0
a 1 1 1 1 0
b 15 16 4 4 0
a 15 15 15 15 1
c 15 15 15 15 2
1 54 54 54 54 2
1 51 51 51 51 2
s 51 51 51 51 2

再打开就会看到box有个1了 就可以insert数据了。当然你需要在jtessboxeditor里从新打开一遍这个数据,不然还是看不到。
6、生成font_properties文件
同样的地方cmd

echo arial 0 0 0 0 0 >font_properties

arial对应着你的字体是什么
如果创建完发现font_properties文件的大小是0,没有写入东西,可以打开强行写入 arial 0 0 0 0 0
7、使用tesseract生成tr训练文件

tesseract num_eng.arial.exp0.tif num_eng.arial.exp0 nobatch box.train

8、生成字符集文件:

unicharset_extractor num_eng.arial.exp0.box

9、生成shape文件:

shapeclustering -F font_properties -U unicharset -O num_eng.unicharset num_eng.arial.exp0.tr

10、生成聚字符特征文件

mftraining -F font_properties -U unicharset -O num_eng.unicharset num_eng.arial.exp0.tr

11、生成字符正常化特征文件

cntraining num_eng.arial.exp0.tr

会生成normproto文件,然后对四个文件从命名一下,分别是inttemp、pffmtable、shapetable、normproto

rename normproto num_eng.normproto
rename inttemp num_eng.inttemp
rename pffmtable num_eng.pffmtable
rename shapetable num_eng.shapetable

命名规则就是[lang].xxx
12、合并训练文件

combine_tessdata num_eng.

python 破解验证码之三:用自己训练的数据跑tesseract识别验证码,最后附上正确率_第6张图片
如果你出现了-1,就说明你哪个步骤出现了错误,检查一下是不是打错字了,然后从新做一遍吧兄嘚
如果没有-1就说明你成功了,把这个traineddata复制到你存放tesseract-OCR文件的tessdata下(好像还要放到python里的tessdata下)
大功告成!!!!!!!!!!!!!!!!!!!!!!

之后再用我之前的代码在新的文件夹生成100个新的验证码做新投入的数据,与训练数据的正确率做对比。再与官方的eng 语言做一下对比,你就知道时间没有白费啦,接下来上图!
python 破解验证码之三:用自己训练的数据跑tesseract识别验证码,最后附上正确率_第7张图片
这是自带的eng语言跑训练数据的正确率,很真实有木有
python 破解验证码之三:用自己训练的数据跑tesseract识别验证码,最后附上正确率_第8张图片
这是我使用我自己的训练后的data再跑训练数据
python 破解验证码之三:用自己训练的数据跑tesseract识别验证码,最后附上正确率_第9张图片
然后是自带的eng跑新投入的数据:更真实了呢python 破解验证码之三:用自己训练的数据跑tesseract识别验证码,最后附上正确率_第10张图片
最后重点来了,我的traineddata跑新投入的数据,这个成功率也就代表了如果你遇到这样的验证码,你的成功率是多少!
python 破解验证码之三:用自己训练的数据跑tesseract识别验证码,最后附上正确率_第11张图片
百分之48,怎么样,是不是觉得之前的投入都值得了哈哈,安装tesseract真的很坑爹,一点都不友好,各种不一样的坑。手动调整数据的时候也是心累啊,一定要认真对待数据标注员这种工种,说不定啥时候就瞎了哈哈。这个结果也就意味着一百个网页有一百个验证码跑100秒的话,你只需要200秒就能结束战斗了,对于这样的结果我个人觉得还是很好的,对于个人来说也相当够用了。
当然各位想要再高一点还是有办法的
FIRST:继续大量投入测试数据,一两百个对于电脑来说根本不能很好的训练到什么,一两百万就差不多了哈哈,这样的话就是公司级别的。大量投入训练数据再由标注员去一点点整很久
SECOND: 自己写一个专门的应对验证码的神经网络,从造轮子开始,最后的结果我见到的高的有96%,甚至能分辨拉伸字体噪点噪线后的O 0 o的区别,这根本连我自己都分不清好不好!!
当然,这些图都是直接投入进去的,灰化二值化之后肯定会有更好的表现,但是二值化的值要随着背景颜色的改变而改变,光灰化不二值化有的验证码压根都看不见字母在哪了。所以我这次也是直接原封不动投入训练数据里。
而且对于不同的网站有不同的验证码,有时候并不能做到很好的识别。还是要针对性的投入训练数据。
总之,学习路上还是要加油啦。这次成功很有成就感,下次我准备学习反编译安卓啦,下次就发反编译安卓的blog!

你可能感兴趣的:(小白自学python)