Keras官方中文文档
本文使用的是keras预训练的Xception模型
官方介绍如下:
Xception
在 ImageNet 上预训练的 Xception V1 模型。
在 ImageNet 上,该模型取得了验证集 top1 0.790 和 top5 0.945 的准确率。
注意该模型只支持 channels_last 的维度顺序(高度、宽度、通道)。
模型默认输入尺寸是 299x299。
参数
include_top: 是否包括顶层的全连接层。
weights: None 代表随机初始化, ‘imagenet’ 代表加载在 ImageNet 上预训练的权值。
input_tensor: 可选,Keras tensor 作为模型的输入(即 layers.Input() 输出的 tensor)。
input_shape: 可选,输入尺寸元组,仅当 include_top=False 时有效(否则输入形状必须是 (299, 299, 3),因为预训练模型是以这个大小训练的)。它必须拥有 3 个输入通道,且宽高必须不小于 71。例如 (150, 150, 3) 是一个合法的输入尺寸。
pooling: 可选,当 include_top 为 False 时,该参数指定了特征提取时的池化方式。
None 代表不池化,直接输出最后一层卷积层的输出,该输出是一个 4D 张量。
‘avg’ 代表全局平均池化(GlobalAveragePooling2D),相当于在最后一层卷积层后面再加一层全局平均池化层,输出是一个 2D 张量。
‘max’ 代表全局最大池化。
classes: 可选,图片分类的类别数,仅当 include_top 为 True 并且不加载预训练权值时可用。
返回值
一个 Keras Model 对象.
keras.applications.xception.Xception(include_top=True, weights='imagenet', input_tensor=None, input_shape=None, pooling=None, classes=1000)
回到验证码识别上,大小写字母+数字一共有62个类别
# 用于生成验证码的字符集
CHAR_SET = ['0', '1', '2', '3', '4', '5', '6', '7', '8',
'9','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',
'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']
# 字符集的长度
CHAR_SET_LEN = 62
# 验证码的长度,每个验证码由4个数字组成
CAPTCHA_LEN = 4
captcha 是用 python 写的生成验证码的库,它支持图片验证码和语音验证码,我们使用的是它生成图片验证码的功能。
pip install captcha
import os
import shutil
import random
import time
from captcha.image import ImageCaptcha
# 用于生成验证码的字符集
CHAR_SET = ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9','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','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']
# 字符集的长度
CHAR_SET_LEN = 62
# 验证码的长度,每个验证码由4个数字组成
CAPTCHA_LEN = 4
# 验证码图片的存放路径
CAPTCHA_IMAGE_PATH = 'train/'
# 用于模型测试的验证码图片的存放路径,它里面的验证码图片作为测试集
TEST_IMAGE_PATH = 'test/'
# 用于模型测试的验证码图片的个数,从生成的验证码图片中取出来放入测试集中
TEST_IMAGE_NUMBER = 2000
# 生成验证码图片,4位的十进制数字可以有10000种验证码
def generate_captcha_image(charSet=CHAR_SET, charSetLen=CHAR_SET_LEN, captchaImgPath=CAPTCHA_IMAGE_PATH):
k = 0
list=[]
for i in range(20001):
captcha_text=''
for i in range(4):
captcha_text += charSet[random.randint(0, 61)]
temp_captcha=captcha_text.upper()
#Windows文件名称不区分大小写,避免生成的验证码重复,用list存储
if temp_captcha not in list:
list.append(temp_captcha)
# fonts = ['./simsun.ttc'],可以加载字体文件生成不同字体的验证码
# image = ImageCaptcha(fonts = ['./simsun.ttc'],width=180,height=60)
image = ImageCaptcha( width=120, height=40)
image.write(captcha_text, captchaImgPath + captcha_text + '.jpg')
k += 1
else:
continue
# 从验证码的图片集中取出一部分作为测试集,这些图片不参加训练,只用于模型的测试
def prepare_test_set():
fileNameList = []
for filePath in os.listdir(CAPTCHA_IMAGE_PATH):
captcha_name = filePath.split('/')[-1]
fileNameList.append(captcha_name)
random.seed(time.time())
random.shuffle(fileNameList)
for i in range(TEST_IMAGE_NUMBER):
name = fileNameList[i]
shutil.move(CAPTCHA_IMAGE_PATH + name, TEST_IMAGE_PATH + name)
if __name__ == '__main__':
generate_captcha_image(CHAR_SET, CHAR_SET_LEN, CAPTCHA_IMAGE_PATH)
prepare_test_set()
用于学校组织的人工智能挑战赛——验证码识别赛,因为数据集的数量有限,所以也用了imgaug库的数据增强,噪声+对比度变换
pip install imgaug
from imgaug import augmenters as iaa
seq = iaa.SomeOf((1, 3), [
iaa.AdditiveGaussianNoise(loc=0, scale=(0.0, 0.1 * 255), per_channel=0.3),
iaa.AdditiveGaussianNoise(loc=1, scale=(0.01, 0.08*255)),
iaa.ContrastNormalization((0.75, 1.5),per_channel=True),
#0.75-1.5随机数值为alpha,对图像进行对比度增强,该alpha应用于每个通道
iaa.AdditiveGaussianNoise(loc=0, scale=(0.0, 0.3*255), per_channel=0.5),
# loc 噪声均值,scale噪声方差,50%的概率,对图片进行添加白噪声并应用于每个通道
iaa.Multiply((0.8, 1.2), per_channel=0.2),
#20%的图片像素值乘以0.8-1.2中间的数值
],random_order=True)
imgs_aug = seq.augment_images(imgs)
链接:https://pan.baidu.com/s/1u4IP4cspT0_g7PnbEZw9mw
提取码:0qji
复制这段内容后打开百度网盘手机App,操作更方便哦(手动狗头doge.jpg)
另外我放的是我没有修改过的数据集,网盘里的图片不是按照xxxx.jpg这种格式的,
而是1.jpg这种按顺序的,不过有对应标签的csv文件,为了方便我就把图片用对应的label重命名了一下,数据集读取的时候也可以用csv文件来读取数据,id是图片名称,label是对应标签,文件路径+id的方式读取图片和对应图片的label
import numpy as np
import glob
from keras.applications.xception import Xception, preprocess_input
from keras.engine.saving import load_model
from keras.layers import Input, Dense, Dropout
from keras.models import Model
from scipy import misc
#数据集文件夹里train是训练文件位置,验证码图片命名为 xxxx.jpg,图片名称就是验证码的label
samples = glob.glob('./train/*.jpg') # 获取所有样本图片
np.random.shuffle(samples) # 将图片打乱
nb_train = 18000 # 共有2万样本,1.8万用于训练,2k用于验证
train_samples = samples[:nb_train]
test_samples = samples[nb_train:]
img_size = (40, 120)
input_image = Input(shape=(img_size[0], img_size[1], 3))
# 直接将验证码输入,做几个卷积层提取特征,然后把这些提出来的特征连接62个分类器,
# 输入图片
# 用预训练的Xception提取特征,采用平均池化
base_model = Xception(input_tensor=input_image, weights='imagenet', include_top=False, pooling='avg')
# 用全连接层把图片特征接上softmax然后62分类,dropout为0.5
# Softmax - 用于多分类神经网络输出
predicts = [Dense(62, activation='softmax')(Dropout(0.5)(base_model.output)) for i in range(4)]
model = Model(inputs=input_image, outputs=predicts)
model.compile(optimizer='adam', loss='sparse_categorical_crossentropy', metrics=['accuracy'])
# model = load_model('./CaptchaXception.h5')#可以加载模型继续训练
def data_generator(data, batch_size): # 样本生成器,节省内存
while True:
# 生成一个从x中抽取的随机数,维度为y的向量,y为抽取次数
batch = np.random.choice(data, batch_size)
x, y = [], []
for img in batch:
x.append(misc.imresize(misc.imread(img), img_size)) # 读取resize图片,再存进x列表
imglabel=str(img).split('\\')[1].split('.')[0]
label=str(imglabel)
# print(label)
y_list = []
for i in label:
# i = i.upper()
if 48 <= ord(i) <= 57:
y_list.append(ord(i) - 48)
if 65 <= ord(i) <= 90:
y_list.append(ord(i) - 55)
if 97 <= ord(i) <= 122:
y_list.append(ord(i) - 61)
y.append(y_list)
# 把验证码标签添加到y列表,把对应字母转化为数字
x = preprocess_input(np.array(x).astype(float))
# 原先是dtype=uint8转成一个纯数字的array
y = np.array(y)
yield x, [y[:, i] for i in range(4)]
# 输出:图片array和四个转化成数字的字母 例如:[array([6]), array([0]), array([3]), array([24])])
ep=10
#持续训练,epoch每10次保存一个模型,下方代码中data_generator(train_samples, 48)是
#每次读取48个数据,就是batchsize,steps_per_epoch是每轮训练的次数,#validation_data是验证集的设置
while True:
model.fit_generator(data_generator(train_samples, 48), steps_per_epoch=375, epochs=10,
validation_data=data_generator(test_samples, 48), validation_steps=40)
model.save('CaptchaXception'+str(ep)+'.h5')
ep+=10
# 保存模型
生成验证的csv文件
import os
from keras.models import load_model
import numpy as np
from scipy import misc
from keras.applications.xception import preprocess_input
import matplotlib.pyplot as plt # plt 用于显示图片
import matplotlib.image as mpimg # mpimg 用于读取图片
import glob
import pandas as pd
img_size = (40, 120)
model = load_model('./CaptchaXception30.h5')
letter_list = [chr(i) for i in range(48, 58)] +[chr(i) for i in range(65, 91)]+[chr(i) for i in range(97, 123)]
def predict(img):
x = []
x.append(misc.imresize(misc.imread(img), img_size))
x = preprocess_input(np.array(x).astype(float))
z = model.predict(x)
# print(z)
z = np.array([i.argmax(axis=1) for i in z]).T
# print(z)
# print('----------------------')
result = z.tolist()
v = []
for i in range(len(result)):
for j in result[i]:
v.append(letter_list[j])
# image = mpimg.imread(test_samples1[n])
# plt.axis('off')
# plt.imshow(image)
# plt.show()
#输出测试结果
str = ''
for i in v:
str += i
return (str)
# print(predict1('./dataset/train/3.jpg'))
def pack(file_names, labels):
frame = pd.DataFrame({'ID':file_names,'label':labels},columns=['ID','label'])
return frame
imgpath='./test/'
imglist=os.listdir(imgpath)
imglist.sort(key=lambda x:int(x[:-4]))
predict_file_name=[]
labels=[]
for i in imglist:
predict_file_name.append(str(i))
# print(imgpath+str(i))
label=predict(imgpath+str(i))
# print(label)
labels.append(label)
frame = pack(predict_file_name, labels)
frame.to_csv('./04.csv', index=False)
模型提交后的准确率结果
后续继续训练以及数据增强训练以后单个模型的准确率是86.733%,从比赛角度上可以生成预测的多个结果csv文件,通过集成学习(Voting投票)获得最佳的csv文件,或许可以达到90%以上的准确率。此外,可以读数据集做图像处理,例如高斯模糊去掉干扰线,灰度图二值化等去掉干扰背景。