Python识别二维码(与生成二维码的代码一同使用)
在二维码识别过程中需要做两部分工作
1.生成分析模型
2.验证码图片识别
建议这两部分分开做,因为在进行模型分析时非常慢,要运行好几个小时,所以可以先设置一个小的区间,看能否成功产生模型,成功后生成所有模型,然后再对其进行分析
from 深度学习.生成二维码 import gen_captcha_text_and_image from 深度学习.生成二维码 import number from 深度学习.生成二维码 import alphabet from 深度学习.生成二维码 import ALPHABET import numpy as np from PIL import Image import tensorflow as tf import time import matplotlib.pyplot as plt import cv2 import os #设置训练参数 IMAGE_HEIGHT=60 IMAGE_WIDTH=160 MAX_CAPTCHA=4 CAPTCHA_IMAGE_PATH="./image" def get_image_file_name(imgpath=CAPTCHA_IMAGE_PATH): filename=[] total=0 for filePath in os.listdir(imgpath): captcha_name=filePath.split('/')[-1] filename.append(captcha_name) total+=1 return filename def gen_data_and_label(i,filePath=CAPTCHA_IMAGE_PATH): FileName=get_image_file_name()[i] pathName=os.path.join(filePath,FileName) img=Image.open(pathName) captcha_image=np.array(img) text = FileName.replace(".jpg", "") return text,captcha_image #自定义一个函数,用来将图片颜色转换成灰色 def convert2gray(img): if len(img.shape)>2: gray=np.mean(img,-1) return gray else: return img char_set=number+alphabet+ALPHABET+['_'] CHAR_SET_LEN=len(char_set) #自定义一个函数,将文本转换成向量 def text2vec(text): text_len=len(text) if text_len>MAX_CAPTCHA: raise ValueError("captcha <=4") vector=np.zeros(MAX_CAPTCHA*CHAR_SET_LEN) def char2pos(c): if c=='_': k=62 return k k=ord(c)-48 if k>9: k=ord(c)-55 if k>35: k=ord(c)-61 if k>61: raise ValueError("No Map") return k for i,c in enumerate(text): idx=i* CHAR_SET_LEN+char2pos(c) vector[idx]=1 return vector #自定义一个函数将向量转换成文本 def vec2text(vec): # char_pos=vec.nonzero()[0] text=[] # for i,c in enumerate(char_pos): for i, c in enumerate(vec): char_at_pos=i 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)) return "".join(text) #自定义一个函数,生成一个训练batch def get_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 #定义X,Y,keep_prob变量 X=tf.placeholder(tf.float32,[None,IMAGE_HEIGHT*IMAGE_WIDTH], name='data-input') Y=tf.placeholder(tf.float32,[None,MAX_CAPTCHA*CHAR_SET_LEN], name='label-input') keep_prob=tf.placeholder(tf.float32, name='keep-prob') #定义一个有3个卷积层的卷积神经网络函数,用来训练 def crack_captcha_cnn(w_alpha=0.01,b_alpha=0.1): x=tf.reshape(X,shape=(-1,IMAGE_HEIGHT,IMAGE_WIDTH,1)) #conv1 # shape[3, 3, 1, 32]里前两个参数表示卷积核尺寸大小,即patch; # 第三个参数是图像通道数,第四个参数是该层卷积核的数量,有多少个卷积核就会输出多少个卷积特征图像 w_c1=tf.Variable(w_alpha*tf.random_normal([3,3,1,32])) # 每个卷积核都配置一个偏置量,该层有多少个输出,就应该配置多少个偏置量 b_c1=tf.Variable(b_alpha*tf.random_normal([32])) # 图片和卷积核卷积,并加上偏执量,卷积结果28x28x32 # tf.nn.conv2d() 函数实现卷积操作 # tf.nn.conv2d()中的padding用于设置卷积操作对边缘像素的处理方式,在tf中有VALID和SAME两种模式 # padding='SAME'会对图像边缘补0,完成图像上所有像素(特别是边缘象素)的卷积操作 # padding='VALID'会直接丢弃掉图像边缘上不够卷积的像素 # strides:卷积时在图像每一维的步长,是一个一维的向量,长度4,并且strides[0]=strides[3]=1 # tf.nn.bias_add() 函数的作用是将偏置项b_c1加到卷积结果value上去; # tf.nn.relu() 函数是relu激活函数,实现输出结果的非线性转换,即features=max(features, 0),输出tensor的形状和输入一致 conv1=tf.nn.relu(tf.nn.bias_add(tf.nn.conv2d(x,w_c1,strides=[1,1,1,1],padding='SAME'),b_c1)) # tf.nn.max_pool()函数实现最大池化操作,进一步提取图像的抽象特征,并且降低特征维度 # ksize=[1, 2, 2, 1]定义最大池化操作的核尺寸为2*2, 池化结果14x14x32 卷积结果乘以池化卷积核 conv1=tf.nn.max_pool(conv1,ksize=[1,2,2,1],strides=[1,2,2,1],padding='SAME') # tf.nn.dropout是tf里为了防止或减轻过拟合而使用的函数,一般用在全连接层; conv1=tf.nn.dropout(conv1,keep_prob) #conv2 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) # 原图像HEIGHT = 60 WIDTH = 160,经过神经网络第一层后输出大小为 30*80*32 #conv3 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) # 经过神经网络第二层运算后输出为 16*40*64 ; 经过第三层输出为 8*20*64,这个参数很重要,决定量后边全连接层的维度 #Fully connected layer w_d=tf.Variable(w_alpha*tf.random_normal([8*20*64,1024])) b_d=tf.Variable(w_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) return out #定义一个训练函数,用来训练模型,并把准确率达到90%的模型保存下来 def train_crack_captcha_cnn(): output=crack_captcha_cnn() # tf.nn.sigmoid_cross_entropy_with_logits()函数计算交叉熵,输出的是一个向量而不是数; # 交叉熵刻画的是实际输出(概率)与期望输出(概率)的距离,也就是交叉熵的值越小,两个概率分布就越接近 # tf.reduce_mean()函数求矩阵的均值 loss=tf.reduce_mean(tf.nn.sigmoid_cross_entropy_with_logits(logits=output,labels=Y)) # tf.train.AdamOptimizer()函数实现了Adam算法的优化器 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,name='predict_max_idx') max_idx_l=tf.argmax(tf.reshape(Y,[-1,MAX_CAPTCHA,CHAR_SET_LEN]),2, name='labels_max_idx') correct_pred=tf.equal(max_idx_p,max_idx_l) accuracy=tf.reduce_mean(tf.cast(correct_pred,tf.float32)) saver=tf.train.Saver() init=tf.global_variables_initializer() with tf.Session() as sess: sess.run(init) for step in range(1,12000+1): step_time = time.time() 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}) if step % 400 ==0 or step==1: 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.}) print("Step="+str(step)+",time:"+str(step_time)+",Training Accuracy="+"{:.3f}".format(acc)) if acc>=0.9 or step==12000: saver.save(sess,"./test/crack_captcha.model",global_step=step) print("Optimization Finished!") #train_crack_captcha_cnn() #生成模型的方法,这部分代码执行很慢 #定义一个测试函数 def crack_captcha_test(): output = crack_captcha_cnn() MODEL_SAVE_PATH = './t1/' saver = tf.train.Saver() with tf.Session() as sess: saver.restore(sess, tf.train.latest_checkpoint(MODEL_SAVE_PATH)) predict = tf.argmax(tf.reshape(output, [-1, MAX_CAPTCHA, CHAR_SET_LEN]), 2) count = 0 for i in range(100): text, image = gen_data_and_label(i) image = convert2gray(image) captcha_image = image.flatten() / 255 text_list = sess.run(predict, feed_dict={X: [captcha_image], keep_prob: 1}) predict_text = text_list[0] print(predict_text) predict_text = vec2text(predict_text) print(predict_text) filePathName = './image/' + text+'.jpg' img=Image.open(filePathName) plt.imshow(img) plt.suptitle(text+'.jpg') plt.subplots_adjust(top=1.3) plt.axis('off') if text == predict_text: count += 1 check_result = " predictions are correct" else: check_result = " predictions are incorrect" plt.title("actual value :{0},predict value:{1},".format(text, predict_text) + check_result) # plt.show() print("actual value :{0},predict value:{1},".format(text, predict_text) + check_result) print("correct rate:" + str(count) + "/100") crack_captcha_test()#模型生成后使用此方法进行分析