验证码数据集下载 https://download.csdn.net/download/qq_42363032/12746911
类别处理—one-hot
验证码字符数是4个
转成one-hot编码是(1, 40)
为方便计算 转成(4, 10) 计算准确率方便找最大值索引
'''
验证码图片如1327,需要对类别标签进行one-hot编码转换
[0,1,0,0,0,0,0,0,0,0,
0,0,0,1,0,0,0,0,0,0,
0,0,1,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,1,0,0]
验证码4个数,对应40个onehot(1, 40), 转成(4, 10)方便计算
'''
def label2oneHot(lable):
vec = numpy.zeros(40)
for i, num in enumerate(lable):
index = i * 10 + int(num)
vec[index] = 1
return vec
'''
灰度处理
对于验证码识别,彩色对于我们是没有用的,转成灰度图
def convert2gray(img):
if img.shape[2] > 2:
r, g, b = img[:, :, 0], img[:, :, 1], img[:, :, 2]
gray = 0.2989 * r + 0.5872 * g + 0.1140 * b # 这些小数加起来的和要小于1(等于1也不行)
return gray
else:
return img
读取图片
- 读取图片
- 灰度处理
- 归一化
- 维度转换 同一尺寸
- 返回ndarray
def get_datasets(file_path, num):
img_list, label_list = [], []
temp = 0
for i in os.listdir(file_path): # 1327.jpg
img = Image.open(file_path + '\\' + i) # 读取图片
img = convert2gray(numpy.array(img)) # 灰度处理 np.array(image) 3维 image 2维
img = img / 255.
img_list.append(img.reshape(IMG_HEIGHT, IMG_WIDTH, 1))
label_list.append(label2oneHot(i[:4]))
temp += 1
if temp >= num:
break
return numpy.array(img_list), numpy.array(label_list)
完整代码
import tensorflow as tf
import tensorflow.contrib as con
import random, os, matplotlib.pyplot as plt, numpy
from PIL import Image
'''
验证码字符数是4个
转成one-hot编码是(1, 40)
为方便计算 转成(4, 10) 计算准确率方便找最大值索引
'''
# 训练集和测试集数量
train_num = 1000
test_num = 100
IMG_HEIGHT = 60 # 图片高度
IMG_WIDTH = 160 # 图片宽度
'''
验证码图片如1327,需要对类别标签进行one-hot编码转换
[0,1,0,0,0,0,0,0,0,0,
0,0,0,1,0,0,0,0,0,0,
0,0,1,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,1,0,0]
验证码4个数,对应40个onehot(1, 40), 转成(4, 10)方便计算
'''
def label2oneHot(lable):
vec = numpy.zeros(40)
for i, num in enumerate(lable):
index = i * 10 + int(num)
vec[index] = 1
return vec
'''
对于验证码识别,彩色对于我们是没有用的,转成灰度图
'''
def convert2gray(img):
if img.shape[2] > 2:
r, g, b = img[:, :, 0], img[:, :, 1], img[:, :, 2]
gray = 0.2989 * r + 0.5872 * g + 0.1140 * b # 这些小数加起来的和要小于1(等于1也不行)
return gray
else:
return img
'''
读取图片
+ 读取图片
+ 灰度处理
+ 归一化
+ 维度转换 同一尺寸
+ 返回ndarray
'''
def get_datasets(file_path, num):
img_list, label_list = [], []
temp = 0
for i in os.listdir(file_path): # 1327.jpg
img = Image.open(file_path + '\\' + i) # 读取图片
img = convert2gray(numpy.array(img)) # 灰度处理 np.array(image) 3维 image 2维
img = img / 255.
img_list.append(img.reshape(IMG_HEIGHT, IMG_WIDTH, 1))
label_list.append(label2oneHot(i[:4]))
temp += 1
if temp >= num:
break
return numpy.array(img_list), numpy.array(label_list)
train_x, train_y = get_datasets(r'G:\A_深度学习1\tensorflow\train', train_num)
test_x, test_y = get_datasets(r'G:\A_深度学习1\tensorflow\test', test_num)
print(train_x.shape, len(train_y))
g_b = 0
def next_batch(X, Y, size):
global g_b
X = X[g_b:g_b + size]
Y = Y[g_b:g_b + size]
g_b = g_b + size
return X, Y
print('==================================')
training_epochs = 100 # 训练总周期
batch_size = 100 # 训练每批样本数
# 占位符 Y: 4个数字的独热编码
X, Y = tf.placeholder('float', shape=[None, IMG_HEIGHT, IMG_WIDTH, 1]), tf.placeholder('float', shape=[None, 40])
# 第一层卷积
with tf.variable_scope('conv1'):
W1 = tf.Variable(tf.random_normal([3, 3, 1, 32]))
L1 = tf.nn.conv2d(X, W1, strides=[1, 1, 1, 1], padding='SAME')
L1 = tf.nn.relu(L1)
L1 = tf.nn.max_pool(L1, ksize=[1, 2, 2, 1], strides=[1, 2, 2, 1], padding='SAME')
# 第二层卷积
with tf.variable_scope('conv2'):
W2 = tf.Variable(tf.random_normal([3, 3, 32, 64]))
L2 = tf.nn.conv2d(L1, W2, strides=[1, 1, 1, 1], padding='SAME')
L2 = tf.nn.relu(L2)
L2 = tf.nn.max_pool(L2, ksize=[1, 2, 2, 1], strides=[1, 2, 2, 1], padding='SAME')
dim = L2.get_shape()[1].value * L2.get_shape()[2].value * L2.get_shape()[3].value
L2 = tf.reshape(L2, [-1, dim])
# 全连接层
with tf.variable_scope('fc'):
W3 = tf.get_variable(name='w3', shape=[dim, 128], initializer=con.layers.xavier_initializer())
b3 = tf.Variable(tf.random_normal([128]))
L3 = tf.nn.relu(tf.matmul(L2, W3) + b3)
W4 = tf.get_variable(name='W4', shape=[128, 40], initializer=con.layers.xavier_initializer(), dtype=tf.float32)
b4 = tf.Variable(tf.random_normal([40]))
logits = tf.matmul(L3, W4) + b4
# 代价函数和优化器
# sigmod_cross适用于每个类别相互独立但不互斥,如图中可以有字母和数字
# softmax_cross适用于每个类别独立且排斥的情况,如数字和字母不可以同时出现
cost = tf.reduce_mean(tf.nn.sigmoid_cross_entropy_with_logits(logits=logits, labels=Y))
optimizer = tf.train.AdamOptimizer(0.001).minimize(cost)
# 准确率计算
predict = tf.argmax(tf.reshape(logits, [-1, 4, 10]), 2) # 在第2轴找最大索引
pre_y = tf.argmax(tf.reshape(Y, [-1, 4, 10]), 2)
acc = tf.reduce_mean(tf.cast(tf.equal(predict, pre_y), 'float'))
with tf.Session() as sess:
sess.run(tf.global_variables_initializer())
for e in range(training_epochs):
avg_cost = 0
total_batch = int(train_num / batch_size)
g_b = 0
for i in range(total_batch):
x, y = next_batch(train_x, train_y, batch_size)
c, _ = sess.run([cost, optimizer], feed_dict={X: x, Y: y})
avg_cost += c / total_batch
if e % 10 == 0:
print('Epoch:', (e + 1), 'cost =', avg_cost, 'acc=',
sess.run(acc, feed_dict={X: train_x, Y: train_y}))
# 测试模型检查准确率
print('正确率:', sess.run(acc, feed_dict={X: test_x, Y: test_y}))
# 在测试集中随机抽一个样本进行测试
r = random.randint(0, test_num - 1)
print("标签: ", sess.run(tf.argmax(test_y[r:r + 1].reshape(4, 10), 1)))
pre = sess.run([tf.argmax(tf.reshape(logits, [4, 10]), 1)], feed_dict={X: test_x[r:r + 1]})
print("预测: ", pre)
plt.imshow(test_x[r].reshape(60, 160))
plt.show()