1. 训练模型代码
import numpy as np import tensorflow as tf # import tensorflow.compat.v1 as tf # tf.disable_v2_behavior() from captcha.image import ImageCaptcha import numpy as np import matplotlib.pyplot as plt from PIL import Image import random number = ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9']
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(): 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, -1) # 上面的转法较快,正规转法如下 # r, g, b = img[:,:,0], img[:,:,1], img[:,:,2] # gray = 0.2989 * r + 0.5870 * g + 0.1140 * b return gray else: return img def text2vec(text): 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): text = [] char_pos = vec.nonzero()[0]# nunzero函数是找出矩阵中非零元素的位置,返回一个元组,每个元素为列表,前一个列表存放非零行坐标,后一个列表存放非零元素列坐标 for i, c in enumerate(char_pos): number = i % 10 text.append(str(number)) 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]) # 有时生成图像大小不是(60, 160, 3) 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 # (image.flatten()-128)/128 mean为0 batch_y[i, :] = text2vec(text) return batch_x, batch_y # 定义CNN def crack_captcha_cnn(w_alpha=0.01, b_alpha=0.1): x = tf.reshape(X, shape=[-1, IMAGE_HEIGHT, IMAGE_WIDTH, 1]) # 3 conv layer w_c1 = tf.Variable(w_alpha * tf.random_normal([3, 3, 1, 32]))#卷积核的参数3x3,深度为1(灰度),32个filter生成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.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 # 训练 def train_crack_captcha_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=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() with tf.Session() as sess: sess.run(tf.global_variables_initializer()) step = 0 while True: 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}) print(step, loss_) # 每100 step计算一次准确率 if step % 10 == 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.}) print(step, acc) # 如果准确率大于90%,保存模型,完成训练 if acc > 0.90: saver.save(sess, "./model/crack_capcha.model", global_step=step) break step += 1 def crack_captcha(captcha_image): output = crack_captcha_cnn() saver = tf.train.Saver() with tf.Session() as sess: saver.restore(sess, "./model/crack_capcha.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__': number = ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9'] 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) 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) # dropout train_crack_captcha_cnn()
2. 测试代码
import numpy as np import tensorflow as tf # import tensorflow.compat.v1 as tf # tf.disable_v2_behavior() from captcha.image import ImageCaptcha import numpy as np import matplotlib.pyplot as plt from PIL import Image import random import cv2 number = ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9'] 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(): 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 = np.array(captcha_image) return captcha_text, captcha_image def convert2gray(img): if len(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 return gray else: return img def text2vec(text): 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): text = [] char_pos = vec.nonzero()[0]# nunzero函数是找出矩阵中非零元素的位置,返回一个元组,每个元素为列表,前一个列表存放非零行坐标,后一个列表存放非零元素列坐标 for i, c in enumerate(char_pos): number = i % 10 text.append(str(number)) return "".join(text) # 定义CNN def crack_captcha_cnn(w_alpha=0.01, b_alpha=0.1): x = tf.reshape(X, shape=[-1, IMAGE_HEIGHT, IMAGE_WIDTH, 1]) # 3 conv layer w_c1 = tf.Variable(w_alpha * tf.random_normal([3, 3, 1, 32]))#卷积核的参数3x3,深度为1(灰度),32个filter生成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.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 def crack_captcha(captcha_image): output = crack_captcha_cnn() saver = tf.train.Saver() with tf.Session() as sess: saver.restore(sess, "./model/crack_capcha.model-3150") 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__': # captcha_text, captcha_image = gen_captcha_text_and_image() # cv2.imwrite('./images/yzm2.jpg', captcha_image)#先生成几张图片 image = cv2.imread('./images/yzm.jpg') print(image.shape) cv2.imshow('yzm', image) cv2.waitKey(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) MAX_CAPTCHA = 4 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(predict_text)
小结:使用自己的CPU,花费了2个半小时左右,刚开始时,准确率一直为0.1左右浮动,一直以为代码问题,或者模型层数不够,继续等待,直到训练1700次个batch后,准确率才慢慢开始上升。本文未对代码做详细分析,需要工程代码或是训练好的模型可以留言,如果想使用GPU训练模型,自己电脑又没有,可以考虑谷歌的colab,一定时长内可以免费使用GPU、TPU,具体找个视频很容易上手。
不足或错误之处,欢迎评论与指正!
标签:nn,text,模型,random,验证码,captcha,tf,识别,image From: https://www.cnblogs.com/wancy/p/17439115.html