Keras框架是一款操作十分简单,高度封装的深度学习框架。在学习完Coursera上AndrewNg的Machine learning课程后,打算用这款框架来实现个验证码识别的小项目。在这里其实更推荐先手动搭建一遍神经网络,比如双隐藏层的神经网络,之后再使用框架来实现自己项目。
当然,Keras框架的高度封装性有两面性啦。对于想要快速实现一个想法,Keras是不二之选。这里给出Keras的中文文档,方便大家学习。
神经网络的训练需要大量的数据,这里通过pillow库来自动生成一定数量的单验证码图片。
from PIL import Image
from PIL import ImageFont
from PIL import ImageDraw
from PIL import ImageFilter
import string
import random
def gen_fake_code(miter,char):
t_size=(18,27)
#字体文件路径
font_path="calibri.ttf"
font=ImageFont.truetype(font_path,20)
txt = Image.new('L', t_size, color='black')
#(3,3)is to change the position of the char in the pic
ImageDraw.Draw(txt).text((3,3), char, fill='white', font=font)
# center不指定,默认为中心点
w = txt.rotate(random.uniform(-20, 20), Image.BILINEAR)
img_ = w.point(lambda i: i < 10, mode='1')
#img_.show()
img_.save('collection/'+str(miter)+'_'+char+'.png')
#图片保存路径
def gen_set():
#生成数
iter_num=30000
#生成26字母和10个数字
char=[chr(i) for i in range(97,123)]
for i in range(10):
char.append(str(i))
for i in range(iter_num):
for k in char:
gen_fake_code(i,k)
将rgb图片的三个像素值转为一个像素值。编写数据载入函数方便在训练前载入数据。
from PIL import Image
import numpy as np
def get_pix(k):
a=(1,2,3)
#转rgb三色为单色
if type(k)==type(a):
r=k[0]*0.333+k[1]*0.333+k[2]*0.333
else:
r=k
return r
def get_image_array(filename):
im=Image.open(filename)
#获取图片宽,高
width,height=im.getbbox()[2],im.getbbox()[3]
#初始化图片像素值矩阵
image_array=[[0 for col in range(width)] for row in range(height)]
im=im.resize((width,height),Image.NEAREST)
for i in range(height):
for j in range(width):
#填充像素矩阵
image_array[i][j]=get_pix(im.getpixel((j,i)))
image=[image_array[i][j] for i in range(height) for j in range(width)]
return image
def load_image(num):
char=[chr(i) for i in range(97,123)]
for i in range(10):
char.append(str(i))
x_data,y_data,x_test,y_test=list(),list(),list(),list()
#所有数据的90%为训练集
for i in range(int(0.9*num)):
for j in range(36):
filename='collection/'+str(i)+'_'+char[j]+'.png'
x_data.append(get_image_array(filename))
y_data.append(j)
#剩下10%为测试集
for i in [k+90 for k in range(int(0.1*num))]:
for j in range(36):
filename='collection/'+str(i)+'_'+char[j]+'.png'
x_test.append(get_image_array(filename))
y_test.append(j)
#返回训练集和测试集
return [x_data,y_data,x_test,y_test]
这里的一些Keras的基本概念不再重复了。需要注意的是,单个验证码图片经过处理成18*27的矩阵了。在数据作为输入时需要除255来使矩阵内元素大小都处于0~1(标准化输入数据)。关于数据的读取和处理,单个图片数据需要从18*27的矩阵转为486*1的矩阵。而图片的读取则在image_handle.py文件中。
from image_handle import load_image
import numpy as np
from keras.models import Sequential
from keras.layers import Dense,Activation
def tran_y(y):
y_ohe=np.zeros(36)
y_ohe[y]=1
return y_ohe
x_data,y_data,x_test,y_test=list(),list(),list(),list()
x_data,y_data,x_test,y_test=load_image(1000)
#读入数据
y_train=np.array([tran_y(y_data[i]) for i in range(len(y_data))])
y_test=np.array([tran_y(y_test[i]) for i in range(len(y_test))])
x_train=np.array(x_data)/255
x_test=np.array(x_test)/255
#标准化数据
model=Sequential()
model.add(Dense(units=300,kernel_initializer='random_uniform',bias_initializer='ones',input_dim=486))
#输入大小是18*27=486
model.add(Activation("relu"))
model.add(Dense(units=100,kernel_initializer='random_uniform',bias_initializer='ones'))
model.add(Activation("relu"))
model.add(Dense(36,kernel_initializer='random_uniform',bias_initializer='ones'))
model.add(Activation("softmax"))
model.compile(loss='binary_crossentropy',optimizer='adam',metrics=['accuracy'])
#模型构建完成
model.fit(x_train,y_train,epochs=1,batch_size=36)
predict=model.predict(x_test)
scores=model.evaluate(x_test,y_test,verbose=2)
print('Real labels:')
print([i.index(1) for i in y_test[0:10].tolist()])
print('Predict is :')
print([i.index(max(i)) for i in predict[0:10].tolist()])
#前十个真实标签与测试值的对比
print(str(scores[1]*100)+'%')
#正确率
在1000个样本的情况下,正确率可以达到100%