簡單的Tensorflow驗證碼識別應用,供大家參考,具體內容如下
1.Tensorflow的安裝方式簡單,在此就不贅述了.
2.訓練集訓練集以及測試及如下(純手工打造,所以數量不多):
3.實現代碼部分(參考了網上的一些實現來完成的)
main.py(主要的神經網絡代碼)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
|
from
gen_check_code
import
gen_captcha_text_and_image_new,gen_captcha_text_and_image
from
gen_check_code
import
number
from
test_check_code
import
get_test_captcha_text_and_image
import
numpy as np
import
tensorflow as tf
text, image
=
gen_captcha_text_and_image_new()
print
(
"驗證碼圖像channel:"
, image.shape)
# (60, 160, 3)
# 圖像大小
IMAGE_HEIGHT
=
image.shape[
0
]
IMAGE_WIDTH
=
image.shape[
1
]
image_shape
=
image.shape
MAX_CAPTCHA
=
len
(text)
print
(
"驗證碼文本最長字符數"
, MAX_CAPTCHA)
# 驗證碼最長4字符; 我全部固定爲4,可以不固定. 如果驗證碼長度小於4,用'_'補齊
# 把彩色圖像轉爲灰度圖像(色彩對識別驗證碼沒有什麼用)
# 度化是將三分量轉化成一樣數值的過程
def
convert2gray(img):
if
len
(img.shape) >
2
:
gray
=
np.mean(img,
-
1
)
# 上面的轉法較快,正規轉法如下
# r, g, b = img[:,:,0], img[:,:,1], img[:,:,2]
# gray = 0.2989 * r + 0.5870 * g + 0.1140 * b
# int gray = (int) (0.3 * r + 0.59 * g + 0.11 * b);
return
gray
else
:
return
img
"""
cnn在圖像大小是2的倍數時性能最高, 如果你用的圖像大小不是2的倍數,可以在圖像邊緣補無用像素。
np.pad(image,((2,3),(2,2)), 'constant', constant_values=(255,)) # 在圖像上補2行,下補3行,左補2行,右補2行
"""
char_set
=
number
# 如果驗證碼長度小於4, '_'用來補齊
CHAR_SET_LEN
=
len
(char_set)
# 文本轉向量
def
text2vec(text):
text_len
=
len
(text)
if
text_len > MAX_CAPTCHA:
raise
ValueError(
'驗證碼最長4個字符'
)
vector
=
np.zeros(MAX_CAPTCHA
*
CHAR_SET_LEN)
def
char2pos(c):
try
:
k
=
ord
(c)
-
ord
(
'0'
)
except
:
raise
ValueError(
'No Map'
)
return
k
for
i, c
in
enumerate
(text):
idx
=
i
*
CHAR_SET_LEN
+
char2pos(c)
vector[idx]
=
1
return
vector
# 向量轉回文本
def
vec2text(vec):
char_pos
=
vec.nonzero()[
0
]
text
=
[]
for
i, c
in
enumerate
(char_pos):
char_at_pos
=
i
# c/63
char_idx
=
c
%
CHAR_SET_LEN
if
char_idx <
10
:
char_code
=
char_idx
+
ord
(
'0'
)
elif
char_idx <
36
:
char_code
=
char_idx
-
10
+
ord
(
'A'
)
elif
char_idx <
62
:
char_code
=
char_idx
-
36
+
ord
(
'a'
)
elif
char_idx
=
=
62
:
char_code
=
ord
(
'_'
)
else
:
raise
ValueError(
'error'
)
text.append(
chr
(char_code))
return
"".join(text)
# 生成一個訓練batch
def
get_next_batch(batch_size
=
128
):
batch_x
=
np.zeros([batch_size, IMAGE_HEIGHT
*
IMAGE_WIDTH])
batch_y
=
np.zeros([batch_size, MAX_CAPTCHA
*
CHAR_SET_LEN])
# 有時生成圖像大小不是(60, 160, 3)
def
wrap_gen_captcha_text_and_image():
while
True
:
text, image
=
gen_captcha_text_and_image_new()
if
image.shape
=
=
image_shape:
return
text, image
for
i
in
range
(batch_size):
text, image
=
wrap_gen_captcha_text_and_image()
image
=
convert2gray(image)
batch_x[i, :]
=
image.flatten()
/
255
# (image.flatten()-128)/128 mean爲0
batch_y[i, :]
=
text2vec(text)
return
batch_x, batch_y
####################################################################
X
=
tf.placeholder(tf.float32, [
None
, IMAGE_HEIGHT
*
IMAGE_WIDTH])
Y
=
tf.placeholder(tf.float32, [
None
, MAX_CAPTCHA
*
CHAR_SET_LEN])
keep_prob
=
tf.placeholder(tf.float32)
# dropout
# 定義CNN
def
crack_captcha_cnn(w_alpha
=
0.01
, b_alpha
=
0.1
):
x
=
tf.reshape(X, shape
=
[
-
1
, IMAGE_HEIGHT, IMAGE_WIDTH,
1
])
# w_c1_alpha = np.sqrt(2.0/(IMAGE_HEIGHT*IMAGE_WIDTH)) #
# w_c2_alpha = np.sqrt(2.0/(3*3*32))
# w_c3_alpha = np.sqrt(2.0/(3*3*64))
# w_d1_alpha = np.sqrt(2.0/(8*32*64))
# out_alpha = np.sqrt(2.0/1024)
# 定義三層的卷積神經網絡
# 定義第一層的卷積神經網絡
# 定義第一層權重
w_c1
=
tf.Variable(w_alpha
*
tf.random_normal([
3
,
3
,
1
,
32
]))
# 定義第一層的偏置
b_c1
=
tf.Variable(b_alpha
*
tf.random_normal([
32
]))
# 定義第一層的激勵函數
conv1
=
tf.nn.relu(tf.nn.bias_add(tf.nn.conv2d(x, w_c1, strides
=
[
1
,
1
,
1
,
1
], padding
=
'SAME'
), b_c1))
# conv1 爲輸入 ksize 表示使用2*2池化,即將2*2的色塊轉化成1*1的色塊
conv1
=
tf.nn.max_pool(conv1, ksize
=
[
1
,
2
,
2
,
1
], strides
=
[
1
,
2
,
2
,
1
], padding
=
'SAME'
)
# dropout防止過擬合。
conv1
=
tf.nn.dropout(conv1, keep_prob)
# 定義第二層的卷積神經網絡
w_c2
=
tf.Variable(w_alpha
*
tf.random_normal([
3
,
3
,
32
,
64
]))
b_c2
=
tf.Variable(b_alpha
*
tf.random_normal([
64
]))
conv2
=
tf.nn.relu(tf.nn.bias_add(tf.nn.conv2d(conv1, w_c2, strides
=
[
1
,
1
,
1
,
1
], padding
=
'SAME'
), b_c2))
conv2
=
tf.nn.max_pool(conv2, ksize
=
[
1
,
2
,
2
,
1
], strides
=
[
1
,
2
,
2
,
1
], padding
=
'SAME'
)
conv2
=
tf.nn.dropout(conv2, keep_prob)
# 定義第三層的卷積神經網絡
w_c3
=
tf.Variable(w_alpha
*
tf.random_normal([
3
,
3
,
64
,
64
]))
b_c3
=
tf.Variable(b_alpha
*
tf.random_normal([
64
]))
conv3
=
tf.nn.relu(tf.nn.bias_add(tf.nn.conv2d(conv2, w_c3, strides
=
[
1
,
1
,
1
,
1
], padding
=
'SAME'
), b_c3))
conv3
=
tf.nn.max_pool(conv3, ksize
=
[
1
,
2
,
2
,
1
], strides
=
[
1
,
2
,
2
,
1
], padding
=
'SAME'
)
conv3
=
tf.nn.dropout(conv3, keep_prob)
# Fully connected layer
# 隨機生成權重
w_d
=
tf.Variable(w_alpha
*
tf.random_normal([
1536
,
1024
]))
# 隨機生成偏置
b_d
=
tf.Variable(b_alpha
*
tf.random_normal([
1024
]))
dense
=
tf.reshape(conv3, [
-
1
, w_d.get_shape().as_list()[
0
]])
dense
=
tf.nn.relu(tf.add(tf.matmul(dense, w_d), b_d))
dense
=
tf.nn.dropout(dense, keep_prob)
w_out
=
tf.Variable(w_alpha
*
tf.random_normal([
1024
, MAX_CAPTCHA
*
CHAR_SET_LEN]))
b_out
=
tf.Variable(b_alpha
*
tf.random_normal([MAX_CAPTCHA
*
CHAR_SET_LEN]))
out
=
tf.add(tf.matmul(dense, w_out), b_out)
# out = tf.nn.softmax(out)
return
out
# 訓練
def
train_crack_captcha_cnn():
# X = tf.placeholder(tf.float32, [None, IMAGE_HEIGHT * IMAGE_WIDTH])
# Y = tf.placeholder(tf.float32, [None, MAX_CAPTCHA * CHAR_SET_LEN])
# keep_prob = tf.placeholder(tf.float32) # dropout
output
=
crack_captcha_cnn()
# loss
# loss = tf.reduce_mean(tf.nn.softmax_cross_entropy_with_logits(output, Y))
loss
=
tf.reduce_mean(tf.nn.sigmoid_cross_entropy_with_logits(output, Y))
# 最後一層用來分類的softmax和sigmoid有什麼不同?
# optimizer 爲了加快訓練 learning_rate應該開始大,然後慢慢衰
optimizer
=
tf.train.AdamOptimizer(learning_rate
=
0.001
).minimize(loss)
predict
=
tf.reshape(output, [
-
1
, MAX_CAPTCHA, CHAR_SET_LEN])
max_idx_p
=
tf.argmax(predict,
2
)
max_idx_l
=
tf.argmax(tf.reshape(Y, [
-
1
, MAX_CAPTCHA, CHAR_SET_LEN]),
2
)
correct_pred
=
tf.equal(max_idx_p, max_idx_l)
accuracy
=
tf.reduce_mean(tf.cast(correct_pred, tf.float32))
saver
=
tf.train.Saver()
with tf.Session() as sess:
sess.run(tf.global_variables_initializer())
step
=
0
while
True
:
batch_x, batch_y
=
get_next_batch(
64
)
_, loss_
=
sess.run([optimizer, loss], feed_dict
=
{X: batch_x, Y: batch_y, keep_prob:
0.75
})
print
(step, loss_)
# 每100 step計算一次準確率
if
step
%
100
=
=
0
:
batch_x_test, batch_y_test
=
get_next_batch(
100
)
acc
=
sess.run(accuracy, feed_dict
=
{X: batch_x_test, Y: batch_y_test, keep_prob:
1.
})
print
(step, acc)
# 如果準確率大於50%,保存模型,完成訓練
if
acc >
0.99
:
saver.save(sess,
"./crack_capcha.model"
, global_step
=
step)
break
step
+
=
1
## 訓練(如果要訓練則去掉下面一行的註釋)
train_crack_captcha_cnn()
def
crack_captcha():
output
=
crack_captcha_cnn()
saver
=
tf.train.Saver()
with tf.Session() as sess:
saver.restore(sess, tf.train.latest_checkpoint(
'.'
))
predict
=
tf.argmax(tf.reshape(output, [
-
1
, MAX_CAPTCHA, CHAR_SET_LEN]),
2
)
count
=
0
# 因爲測試集共40個...寫的很草率
for
i
in
range
(
40
):
text, image
=
get_test_captcha_text_and_image(i)
image
=
convert2gray(image)
captcha_image
=
image.flatten()
/
255
text_list
=
sess.run(predict, feed_dict
=
{X: [captcha_image], keep_prob:
1
})
predict_text
=
text_list[
0
].tolist()
predict_text
=
str
(predict_text)
predict_text
=
predict_text.replace(
"["
, "
").replace("
]
", "
").replace("
,
", "
").replace("
","
")
if
text
=
=
predict_text:
count
+
=
1
check_result
=
",預測結果正確"
else
:
check_result
=
",預測結果不正確"
print
(
"正確: {} 預測: {}"
.
format
(text, predict_text)
+
check_result)
print
(
"正確率:"
+
str
(count)
+
"/40"
)
# 測試(如果要測試則去掉下面一行的註釋)
# crack_captcha()
|
gen_check_code.py(得到訓練集輸入,需要注意修改root_dir爲訓練集的輸入文件夾,下同)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
|
from
|