一.样本制造

首先我们要先制造样本,这里我们制造的样本去除了大小写的o,i和l,加上0-9一共是56个字符。训练的时候大约制造了3万张样本用做训练,2000张用做验证

import cv2
import numpy as npline_num = 5
#图片个数
pic_num = 200
path = "validate/"def randcolor():return (np.random.randint(0, 255), np.random.randint(0, 255), np.random.randint(0, 255))# return (0, 0, 0)def randchar():return np.random.choice([chr(np.random.randint(65, 91)), chr(np.random.randint(97, 123)) ,np.random.randint(0, 9)])def randpos(x_start, x_end, y_start, y_end):return (np.random.randint(x_start, x_end),np.random.randint(y_start, y_end))img_heigth = 60
img_width = 240
for i in range(pic_num):img_name = ""# 生成一个随机矩阵,randint(low[, high, size, dtype])img = np.random.randint(np.random.randint(50, 100), np.random.randint(100, 150), (img_heigth, img_width, 3), np.uint8)# 显示图像cv2.imshow("ranImg",img)x_pos = 0y_pos = 25for i in range(4):char = randchar()while char == 'i' or char == 'I' or char == 'l' or char == 'L' or char == 'o' or char == 'O':char = randchar()img_name += char#各参数依次是:图片,添加的文字,左上角坐标,字体,字体大小,颜色,字体粗细cv2.putText(img, char,(np.random.randint(x_pos, x_pos + 20), np.random.randint(y_pos, y_pos + 20)),cv2.FONT_HERSHEY_SIMPLEX,1.2,randcolor(),3,cv2.LINE_AA)x_pos += 45cv2.imshow("res",img)# 添加线段for i in range(line_num):img = cv2.line(img,randpos(0, img_width, 0, img_heigth),randpos(0, img_width, 0, img_heigth),randcolor(),np.random.randint(1, 2))cv2.imshow("line",img)cv2.imwrite(path + img_name + ".jpg", img)# cv2.waitKey(0)# cv2.destroyAllWindows()

制造的样本如下:

二. 构建CNN神经网络并开始训练

import numpy as np
import osfrom keras.preprocessing import image
from keras.models import Model
from keras.layers import Dense, Dropout, Flatten, Input, concatenate ,BatchNormalization
from keras.layers.convolutional import Conv2D, Convolution2D, MaxPooling2D
from keras.callbacks import ModelCheckpoint
from keras.optimizers import Adadelta
from keras.utils.vis_utils import plot_model
import tensorflow as tf
import glob# 验证码所包含的字符 _表示未知
captcha_word = ['0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F','G','H','J','K','M','N','P','Q','R','S','T','U','V','W','X','Y','Z','a','b','c','d','e','f','g','h','j','k','m','n','p','q','r','s','t','u','v','w','x','y','z']# 图片的长度和宽度
width = 240
height = 60# 每个验证码所包含的字符数
word_len = 4
# 字符总数
word_class = len(captcha_word)samples = glob.glob(r'train/*.jpg')# 验证码素材目录
train_dir = 'data/train'# 生成字符索引,同时反向操作一次,方面还原
char_indices = dict((c, i) for i, c in enumerate(captcha_word))
indices_char = dict((i, c) for i, c in enumerate(captcha_word))# 验证码字符串转数组
def captcha_to_vec(captcha):# 创建一个长度为 字符个数 * 字符种数 长度的数组vector = np.zeros(word_len * word_class)# 文字转成成数组for i, ch in enumerate(captcha):idex = i * word_class + char_indices[ch]vector[idex] = 1return vector# 把数组转换回文字
def vec_to_captcha(vec):text = []# 把概率小于0.5的改为0,标记为错误vec[vec < 0.5] = 0char_pos = vec.nonzero()[0]for i, ch in enumerate(char_pos):text.append(captcha_word[ch % word_class])return ''.join(text)# 自定义评估函数
def custom_accuracy(y_true, y_pred):predict = tf.reshape(y_pred, [-1, word_len, word_class])max_idx_p = tf.argmax(predict, 2)#这个做法牛逼,不用再做stack和reshape了,2,是在Charset那个维度上max_idx_l = tf.argmax(tf.reshape(y_true, [-1, word_len,word_class]), 2)correct_pred = tf.equal(max_idx_p, max_idx_l)_result = tf.map_fn(fn=lambda e: tf.reduce_all(e),elems=correct_pred,dtype=tf.bool)return tf.reduce_mean(tf.cast(_result, tf.float32))#获取目录下样本列表
image_list = []#
for item in os.listdir(train_dir):image_list.append(item)
np.random.shuffle(image_list)
#创建数组,储存图片信息。样本个数、宽度和高度。
# 3代表图片的通道数,如果对图片进行了灰度处理,可以改为单通道 1
X = np.zeros((len(image_list), height, width, 3), dtype = np.uint8)
# 创建数组,储存标签信息
y = np.zeros((len(image_list), word_len * word_class), dtype = np.uint8)for i,img in enumerate(image_list):if i % 10000 == 0:print(i)img_path = train_dir + "/" + img#读取图片raw_img = image.load_img(img_path, target_size=(height, width))#讲图片转为np数组X[i] = image.img_to_array(raw_img)#讲标签转换为数组进行保存y[i] = captcha_to_vec(img.split('.')[0])#创建输入,结构为 高,宽,通道
input_tensor = Input( shape=(height, width, 3))x = input_tensor#构建卷积网络
#两层卷积层,一层池化层,重复3次。因为生成的验证码比较小,padding使用same
x = Convolution2D(32, 3, padding='same', activation='relu')(x)
x = Convolution2D(32, 3, padding='same', activation='relu')(x)
# x= BatchNormalization()(x)
x = MaxPooling2D((2, 2))(x)x = Convolution2D(64, 3, padding='same', activation='relu')(x)
x = Convolution2D(64, 3, padding='same', activation='relu')(x)
# x= BatchNormalization()(x)
x = MaxPooling2D((2, 2))(x)x = Convolution2D(128, 3, padding='same', activation='relu')(x)
x = Convolution2D(128, 3, padding='same',activation='relu')(x)
# x= BatchNormalization()(x)
x = MaxPooling2D((2, 2))(x)#Flatten层用来将输入“压平”,即把多维的输入一维化,常用在从卷积层到全连接层的过渡。
x = Flatten()(x)
#为输入数据施加Dropout。Dropout将在训练过程中每次更新参数时随机断开一定百分比(rate)的输入神经元,Dropout层用于防止过拟合。
x = Dropout(0.25)(x)
x= BatchNormalization()(x)
#Dense就是常用的全连接层
#最后连接4个分类器,每个分类器是56个神经元,分别输出56个字符的概率。
x = [Dense(word_class, activation='softmax', name='c%d'%(i+1))(x) for i in range(word_len)]
# x = [Dense(word_class, activation='sigmoid', name='c%d'%(i+1))(x) for i in range(word_len)]
output = concatenate(x)
#构建模型
model = Model(inputs=input_tensor, outputs=output)
# model.add(BatchNormalization())
#因为训练可能需要数个小时,所以这里加载了之前我训练好的参数。准确率为94%
#可以直接使用此参数继续进行训练,也可以自己从头开始训练
# model.load_weights('model/weights.10--6.55-0.3062.hdf5')#这里优化器选用Adadelta,学习率0.1
opt = Adadelta(lr=0.1)
#编译模型以供训练,损失函数使用 categorical_crossentropy,使用accuracy评估模型在训练和测试时的性能的指标
#这里使用自定义的评估模型
model.compile(loss = 'categorical_crossentropy', optimizer=opt, metrics=['accuracy',custom_accuracy])
#每次epoch都保存一下权重,用于继续训练
checkpointer = ModelCheckpoint(filepath="model/weights.{epoch:02d}--{val_loss:.2f}-{val_acc:.4f}.hdf5",verbose=2, save_weights_only=True)
#开始训练,validation_split代表10%的数据不参与训练,用于做验证急
#我之前训练了50个epochs以上,这里根据自己的情况进行选择。如果输出的val_acc已经达到你满意的数值,可以终止训练
model.fit(X, y, epochs= 10,callbacks=[checkpointer], validation_split=0.1)
# plot model
plot_model(model, to_file='model/model.png', show_shapes=True)#保存权重和模型
model.save_weights('model/captcha_model_weights.h5')
model.save('model/captcha__model_2.h5')

得到的模型图:

部分损失函数:
Loss:

custom_accuracy

3. 结果验证

import numpy as np
import os
import logging
from keras.models import load_model  # 一系列网络层按顺序构成的栈
import glob
from keras.preprocessing import image
import tensorflow as tflogger = logging.getLogger("forecast by model")
# 每个验证码所包含的字符数
word_len = 4
image_path = 'validate/'
# image_path = '20190430/'
# 验证码所包含的字符 _表示未知
captcha_word = ['0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F','G','H','J','K','M','N','P','Q','R','S','T','U','V','W','X','Y','Z','a','b','c','d','e','f','g','h','j','k','m','n','p','q','r','s','t','u','v','w','x','y','z']# 字符总数
word_class = len(captcha_word)#日志初始化
def init_logger():logging.basicConfig(format='%(asctime)s : %(levelname)s : %(message)s',level=logging.DEBUG,handlers=[logging.StreamHandler()])def custom_accuracy(y_true, y_pred):predict = tf.reshape(y_pred, [-1, word_len, word_class])max_idx_p = tf.argmax(predict, 2)#这个做法牛逼,不用再做stack和reshape了,2,是在Charset那个维度上max_idx_l = tf.argmax(tf.reshape(y_true, [-1, word_len,word_class]), 2)correct_pred = tf.equal(max_idx_p, max_idx_l)_result = tf.map_fn(fn=lambda e: tf.reduce_all(e),elems=correct_pred,dtype=tf.bool)return tf.reduce_mean(tf.cast(_result, tf.float32))# load json and create model
def create_model():weight_path = 'model/captcha__model.h5'model = load_model(weight_path,custom_objects={'custom_accuracy': custom_accuracy})return model# 把数组转换回文字
def vec_to_captcha(vec):text = []# 把概率小于0.5的改为0,标记为错误vec[vec < 0.5] = 0char_pos = vec.nonzero()[0]for i, ch in enumerate(char_pos):text.append(captcha_word[ch % word_class])return ''.join(text)if __name__ == '__main__':init_logger()model = create_model()image_list = []for item in os.listdir(image_path):image_list.append(item)np.random.shuffle(image_list)# 图片总数image_count = 0# 成功次数success_count = 0# 图片for i, img in enumerate(image_list):if i % 10000 == 0:print(i)img_path = image_path + img# 读取图片raw_img = image.load_img(img_path, target_size=(60, 240))code = img.replace('.jpg', '')code = code.split('_')[0]logger.debug('正确的验证码为' + code)X_test = np.zeros((1, 60, 240, 3), dtype=np.float32)X_test[0] = image.img_to_array(raw_img)# 预测predict = model.predict(X_test)n = 56  # 大列表中几个数据组成一个小列表arr = []arr.append(predict[0][0:56])arr.append(predict[0][56:112])arr.append(predict[0][112:168])arr.append(predict[0][168:224])predictions = []predictions.append(np.argmax(arr[0]))predictions.append(np.argmax(arr[1]))predictions.append(np.argmax(arr[2]))predictions.append(np.argmax(arr[3]))# predictions = np.argmax(predict, axis=1)# 标签字典keys = range(56)label_dict = dict(zip(keys, captcha_word))result = ''.join([label_dict[pred] for pred in predictions])image_count = image_count + 1if result == code:success_count  = success_count + 1logger.debug("预测的结果为" + result)logger.debug("目前正确率" + str(success_count / image_count))logger.debug("总次数" + str(image_count))logger.debug("成功次数" + str(success_count))logger.debug("正确率" + str(success_count/image_count))

得到的结果:

基于CNN+keras的验证码识别项目相关推荐

  1. 基于卷积神经网络的验证码识别(准确率87.5%+)

    目录 一.任务背景与目标概述 二.卷积神经网络简介 三.方案设计及实现过程 四.实验结果及分析与讨论 五.结论 实现代码 一.任务背景与目标概述 随着现代网络技术的飞速发展和提高,改善了我们的生活质量 ...

  2. 基于CNN的象棋棋子识别

    基于CNN的象棋棋子识别 数据集 数据集介绍 数据预处理 卷积神经网络 什么是卷积神经网络 举个例子 本篇博客用到的卷积神经网络模型 代码及结果展示 代码 结果展示 数据集 数据集介绍 本篇博客采用的 ...

  3. 基于CNN的人脸表情识别系统

    基于CNN的人脸表情识别系统 主要功能: 1)图片识别,可以通过上传本地图片,进行表情识别 2)拍照识别,点击拍照识别按钮,可以调用摄像头实现拍照,并进 行表情识别 实现原理: 1.表情库的建立 fe ...

  4. 基于轻量级CNN的12306验证码识别分析系统

    在我很早的一篇文章中有写过图标型验证码识别的实践项目,这里主要是基于以往的实践经历做出的技术升级,包括:模型轻量化.界面开发.Grad-CAM热力图集成等. 话不多说,首先看效果: 基于CNN的轻量级 ...

  5. 字符验证码识别项目记录

    2019独角兽企业重金招聘Python工程师标准>>> 项目简介: 最近在做一个有趣的项目,需要对某网站的验证码进行识别. 某网站验证码如图:,像素大小:30x106x3 通过人工标 ...

  6. Tensorflow + 基于CNN神经网络的面部表情识别

    最近在学习使用Tensorflow框架,在学习到了CNN卷积神经网络的时候,跟着书上写了一个基于CNN网络的一个面部表情识别的小项目. 说一下我的硬件设备: CPU:G4560,,这什么年代了,我还在 ...

  7. 基于CNn的MINIST手写体识别

    深度学习的上机作业: 基于CNN卷积神经网络的MINIST手写体识别 版本:python-3.9,tensorflow-2.9 目录 MINIST数据集 训练CNN卷积神经网络 使用训练好的模型进行预 ...

  8. 基于TensorFlow的简单验证码识别

    TensorFlow 可以用来实现验证码识别的过程,这里识别的验证码是图形验证码,首先用标注好的数据来训练一个模型,然后再用模型来实现这个验证码的识别. 生成验证码 首先生成验证码,这里使用 Pyth ...

  9. 基于Python的简单验证码识别

    原文链接:有图有真相 摘要:验证码在网络安全方面发挥着关键作用,验证码的主要目的是区分人类和计算机,用来防止自动化脚本对网站的一些恶意行为.目前绝大多数网站都利用验证码来阻止恶意脚本程序的入侵.验证码 ...

最新文章

  1. 免费下载!200+讲者核心观点公布!2021最强AI学术会议视频全部回放
  2. ConcurrentHashMap源码解析(1)
  3. css样式中关于li的横向排列
  4. mysql平台workb_MySQL分布式事务
  5. GDCM:获取SubSequence数据的测试程序
  6. VS中调试时不能关联源代码问题
  7. UITableView的UITableViewStyleGrouped
  8. Leetcode--19. 删除链表的倒数第N个节点
  9. 妹子每天加班1分钟,半年崩溃!向公司索赔55万!
  10. C/C++——从ctime使用到随便测一样冒泡排序和堆排序的效率
  11. Thinapp的昨天,今天和明天
  12. 自定义控件省市区:仿苹果级联菜单
  13. debian mysql中文乱码_MySQL中文乱码的解决方法汇总
  14. 您是哪一种类型的老板?
  15. Mysql千万级数据查询优化技巧
  16. Hyperledger fabric v2.3 通道channel 翻译
  17. 破解ACCESS(2000) .mdb格式文件密码手记
  18. Android重新分区parted,分区工具parted的详解及常用分区使用方法【转】
  19. python 微信自动回复机器人
  20. java 函数参数后加throw_函数后面加throw关键字

热门文章

  1. 【CDT扩展】DSF-GDB分析
  2. pssh Oracle,Linux批量远程管理主机命令_pssh用法详解
  3. 当食品安全遇上“区块链”
  4. 卡莱特led显示屏调试教程_麒麟电子|LED控制卡|LED显示屏|卡莱特同步卡使用千兆网卡调试步骤 通用 - Powered by Discuz!...
  5. LED显示技术应用于智能交通领域的 3 个特点
  6. 小孩儿吃梨问题c语言,C语言编程练习 6.2课上编程练习.docx
  7. 【C++】C++资料整理(持续更新)
  8. 追踪(trace)系统框架设计的思考
  9. 论信息系统项目的整体管理
  10. 分享创意个性古风剪影喜迎国庆PPT模板