captchaIdentify.py
#导入验证码生成的包
A captcha library that generates audio and image CAPTCHAs.
CAPTCHA项目是Completely Automated Public Turing Test to Tell Computers and Humans Apart (全自动区分计算机和人类的图灵测试)的简称,卡内基梅隆大学试图将其注册为商标,但2008年请求被驳回。 CAPTCHA的目的是区分计算机和人类的一种程序算法,是一种区分用户是计算机和人的计算程序,这种程序必须能生成并评价人类能很容易通过但计算机却通不过的测试。
# -*- coding: utf-8 -*-
"""
Created on Sun Feb 24 09:03:05 2019
@author: Administrator
"""
import tensorflow as tf
import numpy as np
import matplotlib.pyplot as plt
from PIL import Image
import random
from captcha.image import ImageCaptcha
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']
#%%
def random_captcha_text(char_set=number+alphabet+ALPHABET,captcha_size=4):
captcha_text=[]
for i in range(captcha_size):
c=random.choice(char_set)
captcha_text.append(c)
return captcha_text
def gen_captcha_text_and_image():
image=ImageCaptcha()
captcha_text=random_captcha_text()
captcha_text=''.join(captcha_text)
captcha=image.generate(captcha_text)
captcha_image=Image.open(captcha)
captcha_image=np.array(captcha_image)
return captcha_text,captcha_image
#%%
if __name__=='__main__':
text,image=gen_captcha_text_and_image()
f=plt.figure()
ax=f.add_subplot(111)
ax.text(.1,.9,text,ha='center',va='center',transform=ax.transAxes)
plt.imshow(image)
生成效果如下:
onlynumber.py
# -*- coding: utf-8 -*-
"""
Created on Sun Feb 24 09:46:47 2019
@author: Administrator
"""
import tensorflow as tf
import numpy as np
import matplotlib.pyplot as plt
from PIL import Image
import random
from captcha.image import ImageCaptcha
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']
#%%
#%%
def random_captcha_text(char_set=number,captcha_size=4):
'生成验证码文本'
captcha_text=[]
for i in range(captcha_size):
c=random.choice(char_set)
captcha_text.append(c)
return captcha_text
def gen_captcha_text_and_image():
'调用random_captcha_text,生成验证码的文本,并产生相应文本的验证码图片,返回值:(验证码label, 验证码图片)'
image=ImageCaptcha()
captcha_text=random_captcha_text()
captcha_text=''.join(captcha_text)
captcha=image.generate(captcha_text)
captcha_image=Image.open(captcha)
captcha_image=np.array(captcha_image)
return captcha_text,captcha_image
#%%
def convert2gray(img):
'将图像转换为灰度图'
if len(img.shape)>2:
gray=np.mean(img,axis=-1)
return gray
else:
return img
def text2vec(text):
'将验证码文本转换为向量'
'此处可以优化,使用onthot编码charset即可,见sklearn中preprocessing中的相应方法'
text_len=len(text)
if text_len>MAX_CAPTCHA:
raise ValueError('验证码最长4个字符')
vector=np.zeros(MAX_CAPTCHA*CHAR_SET_LEN)
for i,c in enumerate(text):
idx=i*CHAR_SET_LEN+int(c)
vector[idx]=1
return vector
#%%
#%%
def vec2text(vec):
"""
char_pos = vec.nonzero()[0]
text=[]
for i, c in enumerate(char_pos):
char_at_pos = i #c/63
char_idx = c % CHAR_SET_LEN
if char_idx < 10:
char_code = char_idx + ord('0')
elif char_idx <36:
char_code = char_idx - 10 + ord('A')
elif char_idx < 62:
char_code = char_idx- 36 + ord('a')
elif char_idx == 62:
char_code = ord('_')
else:
raise ValueError('error')
text.append(chr(char_code))
"""
text=[]
char_pos = vec.nonzero()[0]
for i, c in enumerate(char_pos):
number = i % 10
text.append(str(number))
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
"""
#%%
def gen_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])
def wrap_gen_captcha_text_and_image():
while True:
text,image=gen_captcha_text_and_image()
if image.shape==(60,160,3):
return text,image
for i in range(batch_size):
text,image = wrap_gen_captcha_text_and_image()
image=convert2gray(image)
batch_x[i,:]=image.flatten()/255
batch_y[i,:]=text2vec(text)
return batch_x,batch_y
#%%
def crack_captcha_cnn(w_alpha=0.01,b_alpha=0.1):
'构建破解验证码的CNN网络'
x=tf.reshape(X,shape=[-1,IMAGE_HEIGHT,IMAGE_WIDTH,1])
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)
'fully connected layer'
w_d=tf.Variable(w_alpha*tf.random_normal([8*20*64,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.nn.bias_add(tf.matmul(dense,w_d),b_d))
# dense=tf.nn.max_pool(dense,ksize=[1,2,2,1],strides=[1,2,2,1],padding='SAME')
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)
return out
#%%
def train_crack_captcha_cnn():
'训练CNN'
output=crack_captcha_cnn()
loss=tf.reduce_mean(tf.nn.sigmoid_cross_entropy_with_logits(logits=output,labels=Y))
optimizer=tf.train.AdamOptimizer(learning_rate=.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()
print('session preparing')
with tf.Session() as sess:
print('session created!!')
sess.run(tf.global_variables_initializer())
step=0
print('sess initiated!! ready to train!!')
while True:
# print(step)
batch_x,batch_y=gen_next_batch(64)
_,loss_=sess.run([optimizer,loss],feed_dict={X:batch_x,Y:batch_y,keep_prob:.75})
print('step:',step,'loss:',loss_)
'每100 step计算一次准确率'
if step%10==0:
batch_x_test,batch_y_test=gen_next_batch(100)
acc=sess.run(accuracy,feed_dict={X:batch_x_test,Y:batch_y_test,keep_prob:1.})
print('_____step:',step,'accuracy:',acc,'_____')
if acc > 0.50:
saver.save(sess,'./model/crack_captcha.model',global_step=step)
break
step+=1
#%%
def crack_captcha(captcha_image):
'调用训练好的CNN,输入验证码灰度图,返回CNN预测的text'
output=crack_captcha_cnn()
saver=tf.train.Saver()
with tf.Session() as sess:
saver.restore(sess,'./model/crack_captcha.model-810')
predict=tf.argmax(tf.reshape(output,[-1,MAX_CAPTCHA,CHAR_SET_LEN]),2)
text_list=sess.run(predict,feed_dict={X:[captcha_image],keep_prob:1.})
text=text_list[0].tolist()
return text
#%%
if __name__ == '__main__':
train=1
if train==1:
'train=1的时候训练模型'
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']
text,image=gen_captcha_text_and_image()
print('验证码图像shape:',image.shape) #(60,160,3)
'图像大小'
IMAGE_HEIGHT=60
IMAGE_WIDTH=160
MAX_CAPTCHA=len(text)
print('验证码文本最长字符数:',MAX_CAPTCHA)
'文本转向量'
char_set=number
CHAR_SET_LEN=len(char_set)
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)
train_crack_captcha_cnn()
if train==0:
'train=0的时候调用模型'
number = ['0','1','2','3','4','5','6','7','8','9']
IMAGE_HEIGHT = 60
IMAGE_WIDTH = 160
char_set = number
CHAR_SET_LEN = len(char_set)
text,image=gen_captcha_text_and_image()
f=plt.figure()
ax=f.add_subplot(111)
ax.text(.1,.9,text,ha='center',va='center',transform=ax.transAxes)
plt.imshow(image)
MAX_CAPTCHA=len(text)
image=convert2gray(image)
image=image.flatten()/255
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
predict_text=crack_captcha(image)
print("正确: {} 预测: {}".format(text, predict_text))