CNN深度神经网络实现验证码识别

深度神经网络实现验证码识别

前段时间接到了一个小项目,要做一个验证码的识别,验证码包含数字和英文字母,实现识别的过程用到了CNN网络,最后单个字符的准确率达到90%以上。
方正系统的验证码基本都长这样

准备数据集

登录界面有一个验证码的网址,直接用代码向服务器请求了一万张二维码下来。
在这里插入图片描述
图像处理
先把图片二值化,然后切割成单个的字符。

#将验证码切割保存到每个数据标签文件夹
t=2
n=13
for i in xs_o:
    photo=np.split(i[1], [t,t+n,t+2*n,t+3*n,t+4*n],axis=1)[1:5]
    sp=0
    while sp<4:
        if i[0][sp]==' ':
            st='X'
        else:
            st=i[0][sp]
        if not os.path.exists('yzm_sets/'+st):
            os.mkdir('yzm_sets/'+st)
        matplotlib.image.imsave('yzm_sets/'+st+'/'+st+'_'+str(time.time())+'.png',photo[sp])
        sp+=1

切完了再二值化处理一下

#验证码进行二值化处理
# 图片灰化
CAPTCHA_IMAGE_PATH='yzm_sets_k_2'
from PIL import Image
for j in os.listdir(CAPTCHA_IMAGE_PATH):
    img = Image.open('yzm_sets_k_2/'+j)
    # 模式L”为灰色图像,它的每个像素用8个bit表示,0表示黑,255表示白,其他数字表示不同的灰度。
    Img = img.convert('L')
    # 自定义灰度界限,大于这个值为黑色,小于这个值为白色
    threshold =50

    table = []
    for i in range(256):
        if i < threshold:
            table.append(1)
        else:
            table.append(0)

    # 图片二值化
    photo = Img.point(table, '1')
    photo.save("yzm_sets_kk_2/"+j)

四位数的验证码被切开了

标注训练数据

数据量太大了,我想到一个偷懒的方法,就是用百度的人工智能服务,每天可以免费调用api好几万次吧,够用了,但是识别率不怎么样,我就人工筛选了标注错的。

#调用百度识别API制作数据标签
def get_access_token():
    url='https://aip.baidubce.com/oauth/2.0/token?grant_type=client_credentials&client_id=I3Nc86z2j2MIedoZcGZeSP7P&client_secret=cD8W3vOCcv7kFOdawbK0baoADuVjZSOU'
    html=requests.get(url)
    access_token=json.loads(html.text)['access_token']
    return access_token
def ocr(base64_data,access_token):
    
    url='https://aip.baidubce.com/rest/2.0/ocr/v1/general_basic?access_token='+access_token
    data={
        'image':base64_data
    }
    html=requests.post(url,data=data)
    return json.loads(html.text)
access_token=get_access_token()
IMAGE_PATH='yzm_'
for i in os.listdir(IMAGE_PATH):
    try:
        with open("yzm_/"+i,"rb") as f:#转为二进制格式
            base64_data = base64.b64encode(f.read())#使用base64进行加密
            time.sleep(0.2)
            st=ocr(base64_data ,access_token)
            if len(st['words_result']):
                words=st['words_result'][0]['words']
                if len(words)==4:
                    copyfile("yzm_/"+i, 'yzm_c/'+str(time.time())+'_'+words+'.png')#正确识别
                else:
                    copyfile("yzm_/"+i, 'yzm_w/'+str(time.time())+'_'+words+'.png')#错误识别
            #print(ocr(base64_data ,access_token))
    except:
        print('Error',i)

搭建模型

采用的是主流的CNN架构

  • 独热码映射字典
char='0123456789abcdefghijklmnopqrstuvwxyz'
char2onehot={}
s=0
for i in char:
    y=[0.]*36
    y[s]=1.
    char2onehot[i]=y
    s+=1
  • 定义数据形状
xs=tf.placeholder(tf.float32,[None,27*13])
ys=tf.placeholder(tf.float32,[None,36])
x_image=tf.reshape(xs,shape=[-1,27,13,1])
  • 权重
def w_v(shape):
    return tf.Variable(tf.truncated_normal(shape,stddev=0.5),name='w')
  • 偏置
def b_v(shape):
    b=tf.constant(0.0001,shape=shape)
    return tf.Variable(b,name='b')
  • 卷积
def conv2d(x,W):
    return tf.nn.conv2d(x,W,strides=[1,1,1,1],padding='SAME',name='c')
  • 池化
def max_pooling(x):
    return tf.nn.max_pool(x,ksize=[1,2,2,1],strides=[1,2,2,1],padding='SAME',name='p')
  • `conv1
w1=w_v([5,5,1,4])
b1=b_v([4])
c1=conv2d(x_image,w1)+b1#shape=27,13,1
p1=max_pooling(c1)#shape=,30,4
  • conv2
w2=w_v([5,5,4,8])
b2=b_v([8])
c2=conv2d(p1,w2)+b2#shape=30,30,4
p2=max_pooling(c2)#shape=15,15,8
  • f1
w3=w_v([7*4*8,128])
b3=b_v([128])
f1=tf.nn.relu(tf.matmul(tf.reshape(p2,[-1,7*4*8]),w3)+b3)
  • f2
w4=w_v([128,36])
b4=b_v([36])
f2=tf.matmul(f1,w4)+b4
prediction=tf.nn.softmax(f2)
  • 定义损失函数和优化器
#交叉熵代价损失函数
loss = tf.reduce_mean(tf.nn.softmax_cross_entropy_with_logits(labels=ys, logits=prediction))
train_step=tf.train.AdamOptimizer(le-4).minimize(loss)

完整代码

import tensorflow as tf
import numpy as np
# 定义字符集
char='0123456789abcdefghijklmnopqrstuvwxyz'
char2onehot={}
s=0
for i in char:
    y=[0.]*36
    y[s]=1.
    char2onehot[i]=y
    s+=1
# 定义输入和输出
xs=tf.placeholder(tf.float32,[None,27*13])
ys=tf.placeholder(tf.float32,[None,36])
x_image=tf.reshape(xs,shape=[-1,27,13,1])
# 定义权重和偏置变量
def w_v(shape):
    return tf.Variable(tf.truncated_normal(shape,stddev=0.5),name='w')
def b_v(shape):
    b=tf.constant(0.0001,shape=shape)
    return tf.Variable(b,name='b')
# 定义卷积和池化函数
def conv2d(x,W):
    return tf.nn.conv2d(x,W,strides=[1,1,1,1],padding='SAME',name='c')
def max_pooling(x):
    return tf.nn.max_pool(x,ksize=[1,2,2,1],strides=[1,2,2,1],padding='SAME',name='p')
# 定义神经网络的结构
w1=w_v([5,5,1,4])
b1=b_v([4])
c1=conv2d(x_image,w1)+b1#shape=27,13,1
p1=max_pooling(c1)#shape=,30,4
w2=w_v([5,5,4,8])
b2=b_v([8])
c2=conv2d(p1,w2)+b2#shape=30,30,4
p2=max_pooling(c2)#shape=15,15,8
w3=w_v([7*4*8,128])
b3=b_v([128])
f1=tf.nn.relu(tf.matmul(tf.reshape(p2,[-1,7*4*8]),w3)+b3)
w4=w_v([128,36])
b4=b_v([36])
f2=tf.matmul(f1,w4)+b4
prediction=tf.nn.softmax(f2)
# 定义损失函数和优化器
loss = tf.reduce_mean(tf.nn.softmax_cross_entropy_with_logits(labels=ys, logits=prediction))
train_step=tf.train.AdamOptimizer(1e-4).minimize(loss)
# 准备训练数据集和标签
# ...
# 创建会话并初始化变量
sess = tf.Session()
sess.run(tf.global_variables_initializer())
# 训练过程
for i in range(num_epochs):
    # 从数据集中取出一个batch的数据和标签
    # ...
    # 将batch数据和标签输入神经网络,计算损失函数并更新参数
    _, train_loss = sess.run([train_step, loss], feed_dict={xs: batch_xs, ys: batch_ys})
    # 计算训练集和测试集的准确率
    # ...
    # 输出训练集和测试集的准确率和损失函数
    # ...
# 关闭会话
sess.close()

训练结束后保存模型及加载使用

import tensorflow as tf
# 创建 Saver 对象
saver = tf.train.Saver()
# 训练过程
# ...
# 保存模型
saver.save(sess, "models/model.ckpt")
# 加载模型
saver.restore(sess, "models/model.ckpt")
  • 3
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值