tensorflow练习--汉字验证码识别

简介:

1、做一个汉字验证码的实战,巩固一下深度学习知识。

环境:

1、win10,tensorflow-gpu 1.8  显卡:1060Ti

2、识别的验证码为 四个汉字组成的100x30 像素的图片,每个汉字的位置在一定范围内是随机的,也会随机生成四条干扰线。样式如下:

3、所需文件:最常见3500个汉字的文本:3500.txt;字体文件:我这里使用两个字体文件。

思路:

1、尝试了YOLOv3的思路,直接构建一个网络同时定位加识别每个汉字,确实可以做到,准确率不是很高,在82%左右,后续改进好了也会写博客。

2、本文的思路是,分别训练两个网络,一个网络用来定位每个汉字的位置,也就是预测每个汉字的中心坐标;第二个网络是在第一个网络的基础上去训练识别每一个汉字。这样的做法最后经测试,准确率都在99.2%以上。

两个网络的草图如下:

数据生成:

1、使用pillow库生成验证码。设计一个ImageChar类;

2、rand_img_label() 会根据step参数的值去生成两个网络分别的训练数据,具体看代码注释。

3、rand_img_test() 方法是为了后续测试两个网络的准确率而设计的,返回的是一张验证码和对应四个汉字字符串。

代码:born_data.py

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_img_test(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)

		#把线画上去
		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))

		words,chinese_num=self.rand_chinese()
		#将汉字画上去
		for i in range(len(words)):
			x=start+(self.fontsize+gap)*i+random.randint(0,gap)
			y=random.randint(0,height-self.fontsize-gap)
			self.draw1.text((x,y),words[i],fill=(0,0,0),font=self.font)
		return self.img1,words

	#随机生成一张图片 根据step值,分别为第一个网络和第二个网络提供训练数据
	def rand_img_label(self,num_lines=4,step=1):
		width,height=self.size
		gap=5
		start=0

		self.img1 = Image.new('RGB',self.size,(255,255,255))
		self.draw1=ImageDraw.Draw(self.img1)

		#把线画上去
		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))

		words,chinese_num=self.rand_chinese()
		label_list=[]
		#将汉字画上去
		for i in range(len(words)):
			x=start+(self.fontsize+gap)*i+random.randint(0,gap)
			y=random.randint(0,height-self.fontsize-gap)

			if step == 1:#为第一个网络生成标签数据:汉字的坐标
				temp_list=[0]*2
				temp_list[0]=(x+10)/100#该汉字的中心横坐标,除于100是为了规划到0~1,为了方便训练
				temp_list[1]=(y+14)/25#该汉字的中心纵坐标,除于25也是为了方便训练
			else:#为第二个网络生成标签数据,汉字的one-hot矩阵
				temp_list=[0]*3500
				temp_list[chinese_num[i]]=1
			
			label_list.append(temp_list)
			self.draw1.text((x,y),words[i],fill=(0,0,0),font=self.font)

		return self.img1,label_list

训练第一个网络:预测汉字中心坐标

1、准备数据,对输入数据进行预处理:

(1)将图片转为灰度图;

(2)将图片进行反转黑白颜色的二值化处理,字体变为白色,背景为黑色;

(3)对整个图片矩阵除于255,输入数据就成了 0 和 1 的矩阵。

代码:born_data.py

def prepare_data():
	img_char=ImageChar()
	images=[]
	labels=[]
	for i in range(50000):
		chinese_img_PIL,label_list=img_char.rand_img_label()
		np_img=np.asarray(chinese_img_PIL)
		np_img = cv2.cvtColor(np_img,cv2.COLOR_BGR2GRAY)
		ret,np_img = cv2.threshold(np_img,127,255,cv2.THRESH_BINARY_INV)
		np_img=np_img/255
		images.append(np_img.tolist())
		labels.append(label_list)
		if i % 200==0:
			print(i,end='\r')
	labels=np.array(labels)
	np.save('trainLab0.npy',labels)
	images=np.array(images)
	np.save('trainImg0.npy',images)

 

2、第一个网络的基本信息:

(1)如上网络草图,前三层为卷积+池化层,后三层为全连接层;

(2)前五层激活函数为relu,最后一层为sigmoid,是为了将输出数据归化到0~1;

  • 13
    点赞
  • 66
    收藏
    觉得还不错? 一键收藏
  • 11
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 11
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值