python使用tensorflow深度学习识别验证码
本文介绍了python使用tensorflow深度学习识别验证码,分享给大家,具体如下:
除了传统的PIL包处理图片,然后用pytessert+OCR识别意外,还可以使用tessorflow训练来识别验证码。
此篇代码大部分是转载的,只改了很少地方。
代码是运行在linux环境,tessorflow没有支持windows的python2.7。
gen_captcha.py代码。
#coding=utf-8 fromcaptcha.imageimportImageCaptcha#pipinstallcaptcha importnumpyasnp importmatplotlib.pyplotasplt fromPILimportImage importrandom #验证码中的字符,就不用汉字了 number=['0','1','2','3','4','5','6','7','8','9'] alphabet=['a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q','r','s','t','u', 'v','w','x','y','z'] ALPHABET=['A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P','Q','R','S','T','U', 'V','W','X','Y','Z'] ''' number=['0','1','2','3','4','5','6','7','8','9'] alphabet=[] ALPHABET=[] ''' #验证码一般都无视大小写;验证码长度4个字符 defrandom_captcha_text(char_set=number+alphabet+ALPHABET,captcha_size=4): captcha_text=[] foriinrange(captcha_size): c=random.choice(char_set) captcha_text.append(c) returncaptcha_text #生成字符对应的验证码 defgen_captcha_text_and_image(): while(1): image=ImageCaptcha() captcha_text=random_captcha_text() captcha_text=''.join(captcha_text) captcha=image.generate(captcha_text) #image.write(captcha_text,captcha_text+'.jpg')#写到文件 captcha_image=Image.open(captcha) #captcha_image.show() captcha_image=np.array(captcha_image) ifcaptcha_image.shape==(60,160,3): break returncaptcha_text,captcha_image if__name__=='__main__': #测试 text,image=gen_captcha_text_and_image() printimage gray=np.mean(image,-1) printgray printimage.shape printgray.shape f=plt.figure() ax=f.add_subplot(111) ax.text(0.1,0.9,text,ha='center',va='center',transform=ax.transAxes) plt.imshow(image) plt.show()
train.py代码。
#coding=utf-8
fromgen_captchaimportgen_captcha_text_and_image
fromgen_captchaimportnumber
fromgen_captchaimportalphabet
fromgen_captchaimportALPHABET
importnumpyasnp
importtensorflowastf
"""
text,image=gen_captcha_text_and_image()
print"验证码图像channel:",image.shape#(60,160,3)
#图像大小
IMAGE_HEIGHT=60
IMAGE_WIDTH=160
MAX_CAPTCHA=len(text)
print"验证码文本最长字符数",MAX_CAPTCHA#验证码最长4字符;我全部固定为4,可以不固定.如果验证码长度小于4,用'_'补齐
"""
IMAGE_HEIGHT=60
IMAGE_WIDTH=160
MAX_CAPTCHA=4
#把彩色图像转为灰度图像(色彩对识别验证码没有什么用)
defconvert2gray(img):
iflen(img.shape)>2:
gray=np.mean(img,-1)
#上面的转法较快,正规转法如下
#r,g,b=img[:,:,0],img[:,:,1],img[:,:,2]
#gray=0.2989*r+0.5870*g+0.1140*b
returngray
else:
returnimg
"""
cnn在图像大小是2的倍数时性能最高,如果你用的图像大小不是2的倍数,可以在图像边缘补无用像素。
np.pad(image,((2,3),(2,2)),'constant',constant_values=(255,))#在图像上补2行,下补3行,左补2行,右补2行
"""
#文本转向量
char_set=number+alphabet+ALPHABET+['_']#如果验证码长度小于4,'_'用来补齐
CHAR_SET_LEN=len(char_set)
deftext2vec(text):
text_len=len(text)
iftext_len>MAX_CAPTCHA:
raiseValueError('验证码最长4个字符')
vector=np.zeros(MAX_CAPTCHA*CHAR_SET_LEN)
defchar2pos(c):
ifc=='_':
k=62
returnk
k=ord(c)-48
ifk>9:
k=ord(c)-55
ifk>35:
k=ord(c)-61
ifk>61:
raiseValueError('NoMap')
returnk
fori,cinenumerate(text):
#printtext
idx=i*CHAR_SET_LEN+char2pos(c)
#printi,CHAR_SET_LEN,char2pos(c),idx
vector[idx]=1
returnvector
#printtext2vec('1aZ_')
#向量转回文本
defvec2text(vec):
char_pos=vec.nonzero()[0]
text=[]
fori,cinenumerate(char_pos):
char_at_pos=i#c/63
char_idx=c%CHAR_SET_LEN
ifchar_idx<10:
char_code=char_idx+ord('0')
elifchar_idx<36:
char_code=char_idx-10+ord('A')
elifchar_idx<62:
char_code=char_idx-36+ord('a')
elifchar_idx==62:
char_code=ord('_')
else:
raiseValueError('error')
text.append(chr(char_code))
return"".join(text)
"""
#向量(大小MAX_CAPTCHA*CHAR_SET_LEN)用0,1编码每63个编码一个字符,这样顺利有,字符也有
vec=text2vec("F5Sd")
text=vec2text(vec)
print(text)#F5Sd
vec=text2vec("SFd5")
text=vec2text(vec)
print(text)#SFd5
"""
#生成一个训练batch
defget_next_batch(batch_size=128):
batch_x=np.zeros([batch_size,IMAGE_HEIGHT*IMAGE_WIDTH])
batch_y=np.zeros([batch_size,MAX_CAPTCHA*CHAR_SET_LEN])
#有时生成图像大小不是(60,160,3)
defwrap_gen_captcha_text_and_image():
whileTrue:
text,image=gen_captcha_text_and_image()
ifimage.shape==(60,160,3):
returntext,image
foriinrange(batch_size):
text,image=wrap_gen_captcha_text_and_image()
image=convert2gray(image)
batch_x[i,:]=image.flatten()/255#(image.flatten()-128)/128mean为0
batch_y[i,:]=text2vec(text)
returnbatch_x,batch_y
####################################################################
X=tf.placeholder(tf.float32,[None,IMAGE_HEIGHT*IMAGE_WIDTH])
Y=tf.placeholder(tf.float32,[None,MAX_CAPTCHA*CHAR_SET_LEN])
keep_prob=tf.placeholder(tf.float32)#dropout
#定义CNN
defcrack_captcha_cnn(w_alpha=0.01,b_alpha=0.1):
x=tf.reshape(X,shape=[-1,IMAGE_HEIGHT,IMAGE_WIDTH,1])
#w_c1_alpha=np.sqrt(2.0/(IMAGE_HEIGHT*IMAGE_WIDTH))#
#w_c2_alpha=np.sqrt(2.0/(3*3*32))
#w_c3_alpha=np.sqrt(2.0/(3*3*64))
#w_d1_alpha=np.sqrt(2.0/(8*32*64))
#out_alpha=np.sqrt(2.0/1024)
#3convlayer
w_c1=tf.Variable(w_alpha*tf.random_normal([3,3,1,32]))
b_c1=tf.Variable(b_alpha*tf.random_normal([32]))
conv1=tf.nn.relu(tf.nn.bias_add(tf.nn.conv2d(x,w_c1,strides=[1,1,1,1],padding='SAME'),b_c1))
conv1=tf.nn.max_pool(conv1,ksize=[1,2,2,1],strides=[1,2,2,1],padding='SAME')
conv1=tf.nn.dropout(conv1,keep_prob)
w_c2=tf.Variable(w_alpha*tf.random_normal([3,3,32,64]))
b_c2=tf.Variable(b_alpha*tf.random_normal([64]))
conv2=tf.nn.relu(tf.nn.bias_add(tf.nn.conv2d(conv1,w_c2,strides=[1,1,1,1],padding='SAME'),b_c2))
conv2=tf.nn.max_pool(conv2,ksize=[1,2,2,1],strides=[1,2,2,1],padding='SAME')
conv2=tf.nn.dropout(conv2,keep_prob)
w_c3=tf.Variable(w_alpha*tf.random_normal([3,3,64,64]))
b_c3=tf.Variable(b_alpha*tf.random_normal([64]))
conv3=tf.nn.relu(tf.nn.bias_add(tf.nn.conv2d(conv2,w_c3,strides=[1,1,1,1],padding='SAME'),b_c3))
conv3=tf.nn.max_pool(conv3,ksize=[1,2,2,1],strides=[1,2,2,1],padding='SAME')
conv3=tf.nn.dropout(conv3,keep_prob)
#Fullyconnectedlayer
w_d=tf.Variable(w_alpha*tf.random_normal([8*32*40,1024]))
b_d=tf.Variable(b_alpha*tf.random_normal([1024]))
dense=tf.reshape(conv3,[-1,w_d.get_shape().as_list()[0]])
dense=tf.nn.relu(tf.add(tf.matmul(dense,w_d),b_d))
dense=tf.nn.dropout(dense,keep_prob)
w_out=tf.Variable(w_alpha*tf.random_normal([1024,MAX_CAPTCHA*CHAR_SET_LEN]))
b_out=tf.Variable(b_alpha*tf.random_normal([MAX_CAPTCHA*CHAR_SET_LEN]))
out=tf.add(tf.matmul(dense,w_out),b_out)
#out=tf.nn.softmax(out)
returnout
#训练
deftrain_crack_captcha_cnn():
importtime
start_time=time.time()
output=crack_captcha_cnn()
#loss
#loss=tf.reduce_mean(tf.nn.softmax_cross_entropy_with_logits(output,Y))
loss=tf.reduce_mean(tf.nn.sigmoid_cross_entropy_with_logits(logits=output,labels=Y))
#最后一层用来分类的softmax和sigmoid有什么不同?
#optimizer为了加快训练learning_rate应该开始大,然后慢慢衰
optimizer=tf.train.AdamOptimizer(learning_rate=0.001).minimize(loss)
predict=tf.reshape(output,[-1,MAX_CAPTCHA,CHAR_SET_LEN])
max_idx_p=tf.argmax(predict,2)
max_idx_l=tf.argmax(tf.reshape(Y,[-1,MAX_CAPTCHA,CHAR_SET_LEN]),2)
correct_pred=tf.equal(max_idx_p,max_idx_l)
accuracy=tf.reduce_mean(tf.cast(correct_pred,tf.float32))
saver=tf.train.Saver()
withtf.Session()assess:
sess.run(tf.global_variables_initializer())
step=0
whileTrue:
batch_x,batch_y=get_next_batch(64)
_,loss_=sess.run([optimizer,loss],feed_dict={X:batch_x,Y:batch_y,keep_prob:0.75})
printtime.strftime('%Y-%m-%d%H:%M:%S',time.localtime(time.time())),step,loss_
#每100step计算一次准确率
ifstep%100==0:
batch_x_test,batch_y_test=get_next_batch(100)
acc=sess.run(accuracy,feed_dict={X:batch_x_test,Y:batch_y_test,keep_prob:1.})
printu'***************************************************************第%s次的准确率为%s'%(step,acc)
#如果准确率大于50%,保存模型,完成训练
ifacc>0.9:##我这里设了0.9,设得越大训练要花的时间越长,如果设得过于接近1,很难达到。如果使用cpu,花的时间很长,cpu占用很高电脑发烫。
saver.save(sess,"crack_capcha.model",global_step=step)
printtime.time()-start_time
break
step+=1
train_crack_captcha_cnn()
测试代码:
output=crack_captcha_cnn()
saver=tf.train.Saver()
sess=tf.Session()
saver.restore(sess,tf.train.latest_checkpoint('.'))
while(1):
text,image=gen_captcha_text_and_image()
image=convert2gray(image)
image=image.flatten()/255
predict=tf.argmax(tf.reshape(output,[-1,MAX_CAPTCHA,CHAR_SET_LEN]),2)
text_list=sess.run(predict,feed_dict={X:[image],keep_prob:1})
predict_text=text_list[0].tolist()
vector=np.zeros(MAX_CAPTCHA*CHAR_SET_LEN)
i=0
fortinpredict_text:
vector[i*63+t]=1
i+=1
#break
print("正确:{}预测:{}".format(text,vec2text(vector)))
如果想要快点测试代码效果,验证码的字符不要设置太多,例如0123这几个数字就可以了。
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持毛票票。