效果 先看效果图,左边是 两张测试数据,右边是 预测结果
标注数据集下载地址已更新
文章图片
实现
1. 训练模型 bathcsize 为 700 轮次 50
#!/usr/bin/env python
# coding: utf-8# # 训练模型
#
# ## 引入第三方包# In[1]:from PIL import Image
from keras import backend as K
from keras.utils.vis_utils import plot_model
from keras.models import *
from keras.layers import *import glob
import pickleimport numpy as np
import tensorflow.gfile as gfile
import matplotlib.pyplot as plt# ## 定义超参数和字符集# In[2]:NUMBER = ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9']CAPTCHA_CHARSET = NUMBER# 验证码字符集
CAPTCHA_LEN = 5# 验证码长度
CAPTCHA_HEIGHT = 50# 验证码高度
CAPTCHA_WIDTH = 200# 验证码宽度TRAIN_DATA_DIR = './train-data/'# 验证码数据集目录
TEST_DATA_DIR = './test-data/'BATCH_SIZE = 700
EPOCHS = 50
OPT = 'adam'# adam
LOSS = 'binary_crossentropy'MODEL_DIR = './model/train_demo/'
MODEL_FORMAT = '.h5'
HISTORY_DIR = './history/train_demo/'
HISTORY_FORMAT = '.history'filename_str = "{}captcha_{}_{}_bs_{}_epochs_{}{}"# 模型网络结构文件
MODEL_VIS_FILE = 'captcha_classfication' + '.png'
# 模型文件
MODEL_FILE = filename_str.format(MODEL_DIR, OPT, LOSS, str(BATCH_SIZE), str(EPOCHS), MODEL_FORMAT)
# 训练记录文件
HISTORY_FILE = filename_str.format(HISTORY_DIR, OPT, LOSS, str(BATCH_SIZE), str(EPOCHS), HISTORY_FORMAT)# ## 将 RGB 验证码图像转为灰度图# In[3]:def rgb2gray(img):
# Y' = 0.299 R + 0.587 G + 0.114 B
# https://en.wikipedia.org/wiki/Grayscale#Converting_color_to_grayscale
return np.dot(img[..., :3], [0.299, 0.587, 0.114])# ## 对验证码中每个字符进行 one-hot 编码# In[4]:def text2vec(text, length=CAPTCHA_LEN, charset=CAPTCHA_CHARSET):
text_len = len(text)
# 验证码长度校验
if text_len != length:
raise ValueError('Error: length of captcha should be {}, but got {}'.format(length, text_len))# 生成一个形如(CAPTCHA_LEN*CAPTHA_CHARSET,) 的一维向量
# 例如,4个纯数字的验证码生成形如(4*10,)的一维向量
vec = np.zeros(length * len(charset))
for i in range(length):
# One-hot 编码验证码中的每个数字
# 每个字符的热码 = 索引 + 偏移量
vec[charset.index(text[i]) + i * len(charset)] = 1
return vec# ## 将验证码向量解码为对应字符# In[5]:def vec2text(vector):
if not isinstance(vector, np.ndarray):
vector = np.asarray(vector)
vector = np.reshape(vector, [CAPTCHA_LEN, -1])
text = ''
for item in vector:
text += CAPTCHA_CHARSET[np.argmax(item)]
return text# ## 适配 Keras 图像数据格式# In[6]:def fit_keras_channels(batch, rows=CAPTCHA_HEIGHT, cols=CAPTCHA_WIDTH):
if K.image_data_format() == 'channels_first':
batch = batch.reshape(batch.shape[0], 1, rows, cols)
input_shape = (1, rows, cols)
else:
batch = batch.reshape(batch.shape[0], rows, cols, 1)
input_shape = (rows, cols, 1)return batch, input_shape# ## 读取训练集# In[7]:X_train = []
Y_train = []
for filename in glob.glob(TRAIN_DATA_DIR + '*.jpg'):
X_train.append(np.array(Image.open(filename)))
Y_train.append(filename.lstrip(TRAIN_DATA_DIR).rstrip('.jpg'))# ## 处理训练集图像# In[8]:# list -> rgb(numpy)
X_train = np.array(X_train, dtype=np.float32)
# rgb -> gray
X_train = rgb2gray(X_train)
# normalize
X_train = X_train / 255
# Fit keras channels
X_train, input_shape = fit_keras_channels(X_train)print(X_train.shape, type(X_train))
print(input_shape)# ## 处理训练集标签# In[9]:Y_train = list(Y_train)for i in range(len(Y_train)):
Y_train[i] = text2vec(Y_train[i])Y_train = np.asarray(Y_train)print(Y_train.shape, type(Y_train))# ## 读取测试集,处理对应图像和标签# In[10]:X_test = []
Y_test = []
for filename in glob.glob(TEST_DATA_DIR + '*.jpg'):
X_test.append(np.array(Image.open(filename)))
Y_test.append(filename.lstrip(TEST_DATA_DIR).rstrip('.jpg'))# list -> rgb -> gray -> normalization -> fit keras
X_test = np.array(X_test, dtype=np.float32)
X_test = rgb2gray(X_test)
X_test = X_test / 255
X_test, _ = fit_keras_channels(X_test)Y_test = list(Y_test)
for i in range(len(Y_test)):
Y_test[i] = text2vec(Y_test[i])Y_test = np.asarray(Y_test)print(X_test.shape, type(X_test))
print(Y_test.shape, type(Y_test))# ## 创建验证码识别模型# In[11]:# 输入层
inputs = Input(shape=input_shape, name="inputs")# 第1层卷积
conv1 = Conv2D(32, (3, 3), name="conv1")(inputs)
relu1 = Activation('relu', name="relu1")(conv1)# 第2层卷积
conv2 = Conv2D(32, (3, 3), name="conv2")(relu1)
relu2 = Activation('relu', name="relu2")(conv2)
pool2 = MaxPooling2D(pool_size=(2, 2), padding='same', name="pool2")(relu2)# 第3层卷积
conv3 = Conv2D(64, (3, 3), name="conv3")(pool2)
relu3 = Activation('relu', name="relu3")(conv3)
pool3 = MaxPooling2D(pool_size=(2, 2), padding='same', name="pool3")(relu3)# 将 Pooled feature map 摊平后输入全连接网络
x = Flatten()(pool3)# Dropout
x = Dropout(0.25)(x)# 4个全连接层分别做10分类,分别对应4个字符。
x = [Dense(10, activation='softmax', name='fc%d' % (i + 1))(x) for i in range(5)]# 4个字符向量拼接在一起,与标签向量形式一致,作为模型输出。
outs = Concatenate()(x)# 定义模型的输入与输出
model = Model(inputs=inputs, outputs=outs)
model.compile(optimizer=OPT, loss=LOSS, metrics=['accuracy'])# ## 查看模型摘要# In[12]:model.summary()# ## 模型可视化# In[13]:plot_model(model, to_file=MODEL_VIS_FILE, show_shapes=True)# ## 训练模型# In[14]:history = model.fit(X_train,
Y_train,
batch_size=BATCH_SIZE,
epochs=EPOCHS,
verbose=2,
validation_data=https://www.it610.com/article/(X_test, Y_test))# ## 预测样例# In[47]:print(vec2text(Y_test[9]))# In[48]:yy = model.predict(X_test[9].reshape(1, 50, 200, 1))# In[49]:print(vec2text(yy))# ## 保存模型# In[50]:if not gfile.Exists(MODEL_DIR):
gfile.MakeDirs(MODEL_DIR)model.save(MODEL_FILE)
print('Saved trained model at %s ' % MODEL_FILE)# ## 保存训练过程记录# In[51]:print(history.history['acc'])# In[52]:history.history.keys()# In[53]:if gfile.Exists(HISTORY_DIR) == False:
gfile.MakeDirs(HISTORY_DIR)# with open(HISTORY_FILE, 'wb') as f:
#pickle.dump(history.history, f)# In[54]:# print(HISTORY_FILE)# In[ ]:
2 模型结构设计
文章图片
3. 建立预测服务
import base64import numpy as np
import tensorflow as tffrom io import BytesIO
from flask import Flask, request, jsonify
from keras.models import load_model
from PIL import ImageNUMBER = ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9']
LOWERCASE = ['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']
UPPERCASE = ['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']CAPTCHA_CHARSET = NUMBER# 验证码字符集
CAPTCHA_LEN = 5# 验证码长度
CAPTCHA_HEIGHT = 50# 验证码高度
CAPTCHA_WIDTH = 200# 验证码宽度# 10 个 Epochs 训练的模型 rmspropadam
MODEL_FILE = './model/train_demo/captcha_adam_binary_crossentropy_bs_700_epochs_50.h5'def vec2text(vector):
if not isinstance(vector, np.ndarray):
vector = np.asarray(vector)
vector = np.reshape(vector, [CAPTCHA_LEN, -1])
text = ''
for item in vector:
text += CAPTCHA_CHARSET[np.argmax(item)]
return textdef rgb2gray(img):
# Y' = 0.299 R + 0.587 G + 0.114 B
# https://en.wikipedia.org/wiki/Grayscale#Converting_color_to_grayscale
return np.dot(img[...,:3], [0.299, 0.587, 0.114])app = Flask(__name__) # 创建 Flask 实例# 测试 URL
@app.route('/ping', methods=['GET', 'POST'])
def hello_world():
return 'pong'# 验证码识别 URL
@app.route('/predict', methods=['POST'])
def predict():
response = {'success': False, 'prediction': '', 'debug': 'error'}
received_image= False
if request.method == 'POST':
if request.files.get('image'): # 图像文件
image = request.files['image'].read()
# print("image is ")
# print(image)
received_image = True
response['debug'] = 'get image'
elif request.get_json(): # base64 编码的图像文件
encoded_image = request.get_json()['image']
image = base64.b64decode(encoded_image)
received_image = True
response['debug'] = 'get json'
if received_image:
image = np.array(Image.open(BytesIO(image)))
image = rgb2gray(image).reshape(1, 50, 200, 1).astype('float32') / 255
with graph.as_default():
pred = model.predict(image)
response['prediction'] = response['prediction'] + vec2text(pred)
response['success'] = True
response['debug'] = 'predicted'
else:
response['debug'] = 'No Post'
return jsonify(response)model = load_model(MODEL_FILE) # 加载模型
graph = tf.get_default_graph() # 获取 TensorFlow 默认数据流图# 启动命令
# export FLASK_ENV=development && flask run --host=0.0.0.0
# curl 127.0.0.1:5000/ping
# curl -X POST -F image=@/root/Workspace/leon/test-data/56497.jpg 'http://localhost:5000/predict'
4 数据集下载 【python|Keras TensorFlow 验证码识别(附数据集)】train-data.zip
推荐阅读
- C语言学习|第十一届蓝桥杯省赛 大学B组 C/C++ 第一场
- paddle|动手从头实现LSTM
- pytorch|使用pytorch从头实现多层LSTM
- 推荐系统论文进阶|CTR预估 论文精读(十一)--Deep Interest Evolution Network(DIEN)
- Python专栏|数据分析的常规流程
- pytorch|YOLOX 阅读笔记
- Python|Win10下 Python开发环境搭建(PyCharm + Anaconda) && 环境变量配置 && 常用工具安装配置
- Python绘制小红花
- Pytorch学习|sklearn-SVM 模型保存、交叉验证与网格搜索
- 前沿论文|论文精读(Neural Architecture Search without Training)