alexqdjay

## 步骤

1. 采集验证码图片
2. 处理图片：灰度、去噪、分割
3. 分类图片，准备训练数据：将0-9数字图片放入对应文件夹，转化成数据
4. 编写训练模型
5. 调用模型，形成识别系统

## 处理图片

### 灰度化

``int gray = (int) (0.3 * r + 0.59 * g + 0.11 * b);``

``gray = gray < 127 ? 0 : 255;``

### 分割图片

1. 扫描出每个数字左右边界，即找到最左最右的点
2. 根据这个边界进行横向裁剪
3. 如果发现最后裁剪出来不是4个数字而是3个或者更少，查看是否存在某个裁剪块的宽度比一般的要大，然后进行平均分割
4. 对每个裁剪下来的图片再进行纵向裁剪，将上下多余的空白区裁剪掉

## 分类图片，准备训练数据

``0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,....``

``````[1, 0, 0, 0, 0, 0, 0, 0, 0, 0]  // 表示0
[0, 0, 0, 0, 0, 1, 0, 0, 0, 0]  // 表示5``````

## 编写训练模型

### CNN

TF提供2维卷积函数

``tf.nn.conv2d(x, W, strides=[1, 1, 1, 1], padding='SAME')``

``tf.nn.max_pool(x, ksize=[1,2,2,1], strides=[1,2,2,1], padding='SAME')``

x是输入；ksize表示使用2x2池化，即将2x2的色块降为1x1，最大池化会保留灰度值最高的那个像素点；因为需要整体缩小图片所以这里strides在横向纵向的步长都为2。

### 构建处理层

``````def weight_variable(shape, name):
initial = tf.truncated_normal(shape, stddev=0.1)
return tf.Variable(initial, name=name)

def bias_variable(shape, name):
initial = tf.constant(0.1, shape=shape)
return tf.Variable(initial, name=name)

def conv2d(x, W):
# stride [1, x_movement, y_movement, 1]
return tf.nn.conv2d(x, W, strides=[1, 1, 1, 1], padding='SAME')

def max_pool_2x2(x):
# stride [1, x_movement, y_movement, 1]

#define weights & biases
weights = {
"h1": weight_variable([5, 5, 1, 32], "w_h1"),
"h2": weight_variable([5, 5, 32, 64], "w_h2"),
"f1": weight_variable([9*9*64, 1024], "w_f1"),
"f2": weight_variable([1024, 10], "w_f2")
}

biases = {
"h1": bias_variable([32], "b_h1"),
"h2": bias_variable([64], "b_h2"),
"f1": bias_variable([1024], "b_f1"),
"f2": bias_variable([10], "b_f2")
}

x_image = tf.reshape(xs, [-1, 36, 36, 1]) # [n_samples, 28,28,1]

## conv1 layer ##
W_conv1 = weights["h1"] # patch 5x5, in size 1, out size 32
b_conv1 = biases["h1"]
h_conv1 = tf.nn.relu(conv2d(x_image, W_conv1) + b_conv1) # output size 36x36x32
h_pool1 = max_pool_2x2(h_conv1)                          # output size 18x18x32

## conv2 layer ##
W_conv2 = weights["h2"] # patch 5x5, in size 32, out size 64
b_conv2 = biases["h2"]
h_conv2 = tf.nn.relu(conv2d(h_pool1, W_conv2) + b_conv2) # output size 18x18x64
h_pool2 = max_pool_2x2(h_conv2)                          # output size 9x9x64

## fc1 layer ##
W_fc1 = weights["f1"]
b_fc1 = biases["f1"]
# [n_samples, 9, 9, 64] ->> [n_samples, 9*9*64]
h_pool2_flat = tf.reshape(h_pool2, [-1, 9*9*64])
h_fc1 = tf.nn.relu(tf.matmul(h_pool2_flat, W_fc1) + b_fc1)
h_fc1_drop = tf.nn.dropout(h_fc1, keep_prob)

## fc2 layer ##
W_fc2 = weights["f2"]
b_fc2 = biases["f2"]
prediction = tf.nn.softmax(tf.matmul(h_fc1_drop, W_fc2) + b_fc2)``````

### 定义Loss和Optimizer

``````cross_entropy = tf.reduce_mean(-tf.reduce_sum(ys * tf.log(prediction),
reduction_indices=[1]))       # loss

### 执行训练

``````for i in range(150):
sess.run(train_step, feed_dict={xs: datas, ys: labels, keep_prob: 0.5})``````

### 计算正确率

``````#y_pre 是每个数据对应各个类别（0-9）的概率如[[0.1,0.2,0.3,0.4...],[0.2,0.1,0.9....]]
y_pre = sess.run(prediction, feed_dict={xs: test_datas, keep_prob: 1})
#tf.argmax返回最大数的索引，再比较预测数据索引和测试数据真实索引
correct_prediction = tf.equal(tf.argmax(y_pre,1), tf.argmax(test_labels,1))
#将上面比较结果True转为1，False转为0，相加计算平均值
accuracy = tf.reduce_mean(tf.cast(correct_prediction, tf.float32))
result = sess.run(accuracy)``````

## 调用模型

### 保存模型

``````saver = tf.train.Saver()
save_path = saver.save(sess, "./models/save_net.ckpt")``````

### 恢复模型

``````saver = tf.train.Saver()
saver.restore(sess, "./final_models/save_net.ckpt")``````

## 总结

### 评论(9)

#### 引用来自“红薯”的评论

DYBOY
2018/11/26
0
0
Python视频教程，带你玩转Python深度学习，TensorFlow框架使用教程分享！

01/02
156
0
ResNet网络识别验证码实战练习——高准确率的机器学习模型

MrLonelyZC88
01/07
0
0
tensorflow 实现端到端的OCR：二代身份证号识别

2017/08/08
0
0

08/14
0
0

mysql-connector-java升级到8.0后保存时间到数据库出现了时差

ValSong
59分钟前
5
0
Spring Boot 如何部署到 Linux 中的服务

honeymoose

6
0
Spring Boot 2 实战：使用 Spring Boot Admin 监控你的应用

1. 前言 生产上对 Web 应用 的监控是十分必要的。我们可以近乎实时来对应用的健康、性能等其他指标进行监控来及时应对一些突发情况。避免一些故障的发生。对于 Spring Boot 应用来说我们可以...

6
0
ZetCode 教程翻译计划正式启动 | ApacheCN

ApacheCN_飞龙

4
0
CSS定位

CSS定位 relative相对定位 absolute绝对定位 fixed和sticky及zIndex relative相对定位 position特性：css position属性用于指定一个元素在文档中的定位方式。top、right、bottom、left属性则...

studywin

7
0