本人已有新的想法,识别率比本文高,前往https://blog.csdn.net/qq_34896470/article/details/85073562
简介:
接上一篇中文验证码的分割,这一篇继续说一下中文验证码的识别,关于中文验证码的分割详细请看上一篇,但这里也会做一下说明。尝试识别的验证码样式如下:
思路:
中文的数量是英文数字不可比拟的,就拿中文汉字的数量是英文字母不可比的,就拿本文所使用的常用3500个汉字来说,就上图四个汉字验证码来说,如果不对验证码分割直接使用神经网络进行端到端识别的话,学习成本会非常大,其次,网络输出层需要3500的4次方个类别,这样的计算量是相当庞大的。
所以本文的思路是学习训练两个神经网络模型。
第一个模型为全卷积神经网络,作用是检测验证码中汉字的位置,方便将汉字分割为20x20像素的图片。网络总共为7层(画图偷懒了,只画了5层),前三层为卷积➕ 池化层,后三层为图片resize放大➕ 卷积层,输入和输出如下图所示,数据是本人生成的,代码以及网络详细结构在上一篇中。
第二个模型为普通卷积神经分类网络,作用是对分割出的汉字进行识别。网络前半部分为卷积+池化层,后半部分为全连接层,输出为softmax层,输出为对3500个常用字的预测。
当两个模型训练完之后,程序将按照如下如下流程图对中文验证码进行汉字识别(也就是本文最后一段代码的流程图):
数据的生成:
第一个模型数据的生成请看上一篇文章。
第二个模型数据的生成:
1、首先从3500.txt文件中读取最常用的3500个汉字,随机挑选出四个汉字,并记录每个汉字在这3500个汉字的位置作为标签。
2、将挑选出的汉字画在一张30x100像素的图片上,汉字位置在一定范围内存在随机性,并随机画上一些噪音杂线干扰识别。
from PIL import Image,ImageFont,ImageDraw
import random
import os
import numpy as np
import cv2
class ImageChar():
"""
1、读取3500.txt 这是最常用3500汉字 并随机挑选出汉字
2、在./fonts/ 文件夹下存放 字体格式 随机挑选格式 然后依据格式随机生成汉字
3、随机画指定数目的干扰线
4、环境:Mac python3.5
"""
def __init__(self, color=(0,0,0),size=(100,30),
fontlist=['./fonts/'+i for i in os.listdir('./fonts/') if not i =='.DS_Store'],
fontsize=20,
num_word=4):#生成多少个字的验证码(图片宽度会随之增加)
self.num_word=num_word
self.color=color
self.fontlist=fontlist
if self.num_word==4:
self.size=size
else:
self.size=((self.fontsize+5)*self.num_word,40)
#随机挑选一个字体 randint(0,2)会取0,1,2 所以减去 1
self.fontpath=self.fontlist[random.randint(0,len(self.fontlist)-1)]
self.fontsize=fontsize
self.chinese=open('3500.txt','r').read()
self.font=ImageFont.truetype(self.fontpath, self.fontsize)
#随机生成四个汉字的字符串
def rand_chinese(self):
chinese_str=''
chinese_num=[]
for i in range(self.num_word):
temp=random.randint(0,3499)
chinese_str=chinese_str+self.chinese[temp]
chinese_num.append(temp)
return chinese_str,chinese_num
#随机生成杂线的坐标
def rand_line_points(self,mode=0):
width,height=self.size
if mode==0:
return (random.randint(0, width), random.randint(0, height))
elif mode==1:
return (random.randint(0,6),random.randint(0, height))
elif mode==2:
return (random.randint(width-6,width),random.randint(0, height))
#随机生成一张 输入 图片 和 一张 标签图片(模型一:检测汉字区域)
def rand_draw(self,num_lines=4):
width,height=self.size
gap=5
start=0
#第一张,带噪音的验证码
self.img1 = Image.new('RGB',self.size,(255,255,255))
self.draw1=ImageDraw.Draw(self.img1)
self.img2 = Image.new('RGB',self.size,(255,255,255))
self.draw2=ImageDraw.Draw(self.img2)
#把线画上去
for i in range(num_lines//2):
self.draw1.line([self.rand_line_points(),self.rand_line_points()],(0,0,0))
for i in range(num_lines//2):
self.draw1.line([self.rand_line_points(1),self.rand_line_points(2)],(0,0,0))
i=0
words,chinese_num=self.rand_