config.py
from os.path import join
f = open('./chinese.txt', 'r', encoding='utf-8')#加載3500個常用漢字
CH_CHAR = []
lines = f.read()
f.close()
CH_CHAR = eval(lines)
number = ['0','1','2','3','4','5','6','7','8','9','·']
ALPHABET = ['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']
# 如果驗證碼長度小於4, '_'用來補齊
gen_char_set = number+ ALPHABET + CH_CHAR + ['_']
IMAGE_HEIGHT = 76
IMAGE_WIDTH = 420
MAX_CAPTCHA = 33
CHAR_SET_LEN = len(gen_char_set)
run.py
#encoding:utf-8
from PIL import Image
import train
import sys
def run(image_path):
image = Image.open(image_path)
image = train.convert2gray(image)
image = image.flatten() / 255
predict_text = train.crack_captcha(image)
file = open('C:/Users/Administrator/Desktop/' + predict_text + '.txt', 'w')
file.write(predict_text)
print("succ")
return "".join(predict_text)
run(sys.argv[1])
"""
image_path = sys.argv[1]
image = Image.open(image_path)
image = train.convert2gray(image)
image = image.flatten() / 255
predict_text = train.crack_captcha(image)
file = open('C:/Users/Administrator/Desktop/' + predict_text + '.txt', 'w')
file.write(predict_text)
"""
train.py
#encoding:utf-8
import tensorflow as tf
import numpy as np
from config import IMAGE_WIDTH, IMAGE_HEIGHT, MAX_CAPTCHA, CHAR_SET_LEN, gen_char_set
import os
import random
import math
from PIL import Image
import sys
def convert2gray(image):
if len(image.shape) > 2:
gray = np.mean(image, -1)
#上面的轉換方法較快,正規轉法如下
#r, g, b = image[:, :, 0], image[:, :, 1], image[:, :, 2]
#gray = 0.2989 * r + 0.5870 * g + 0.1140 * b
return gray
else:
return image
def gen_captch_text_and_image():
all_image = os.listdir("F:/D/")
random_file = random.randint(0, 5)
base = os.path.basename("F:/D/" + all_image[random_file])
text = os.path.splitext(base)[0]
image = Image.open("F:/D/" + all_image[random_file])
#image.save("F:/E/" + text + ".png")
image = np.array(image)
return text, image
"""
cnn在圖像大小是2的倍數時性能最高, 如果你用的圖像大小不是2的倍數,可以在圖像邊緣補無用像素。
np.pad(image,((2,3),(2,2)), 'constant', constant_values=(255,)) # 在圖像上補2行,下補3行,左補2行,右補2行
"""
"""
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):
if c == '_':
k = 62
return k
k = ord(c) - 48
if k > 9:
k = ord(c) - 55
if k > 35:
k = ord(c) - 61
if k > 61:
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
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)
"""
def text2vec(text):
#
text_len = len(text)
if text_len > MAX_CAPTCHA:
print("warming: ", text)
raise ValueError('驗證碼最長MAX_CAPTCHA個字符')
#
vector = np.zeros(MAX_CAPTCHA * CHAR_SET_LEN)
for i, c in enumerate(text):
#
idx = i * CHAR_SET_LEN + gen_char_set.index(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
char_idx = c % CHAR_SET_LEN
char_code = gen_char_set[char_idx]
text.append(char_code)
return "".join(text)
def get_next_batch(batch_size = 64):
batch_x = np.zeros([batch_size, IMAGE_HEIGHT * IMAGE_WIDTH])
batch_y = np.zeros([batch_size, MAX_CAPTCHA * CHAR_SET_LEN])
for i in range(batch_size):
text, image = gen_captch_text_and_image()
image = convert2gray(image)
batch_x[i, :] = image.flatten() / 255
batch_y[i, :] = text2vec(text)
str = text
return batch_x, batch_y, str
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)
def crack_captcha_cnn(w_alpha = 0.01, b_alpha = 0.1):
x = tf.reshape(X, shape=[-1, IMAGE_HEIGHT, IMAGE_WIDTH, 1])
L1_NEU_NUM = 128
L2_NEU_NUM = 256
L3_NEU_NUM = 512
L4_NEU_NUM = 512
CONV_CORE_SIZE = 5
MAX_POOL_NUM = 4
FULL_LAYER_FEATURE_NUM = 1024
w_c1 = tf.Variable(w_alpha * tf.random_normal([CONV_CORE_SIZE, CONV_CORE_SIZE, 1, L1_NEU_NUM]))
b_c1 = tf.Variable(b_alpha * tf.random_normal([L1_NEU_NUM]))
conv1 = tf.nn.relu(tf.nn.bias_add(tf .nn.conv2d(x, w_c1, strides=[1, 1, 1, 1], padding="SAME"), b_c1))
conv1 = tf.nn.max_pool(conv1, ksize=[1, 2, 2, 1], strides=[1, 2, 2, 1], padding="SAME")
conv1 = tf.nn.dropout(conv1, keep_prob)
w_c2 = tf.Variable(w_alpha * tf.random_normal([CONV_CORE_SIZE, CONV_CORE_SIZE, L1_NEU_NUM, L2_NEU_NUM]))
b_c2 = tf.Variable(b_alpha * tf.random_normal([L2_NEU_NUM]))
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([CONV_CORE_SIZE, CONV_CORE_SIZE, L2_NEU_NUM, L3_NEU_NUM]))
b_c3 = tf.Variable(b_alpha * tf.random_normal([L3_NEU_NUM]))
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)
w_c4 = tf.Variable(w_alpha * tf.random_normal([CONV_CORE_SIZE, CONV_CORE_SIZE, L3_NEU_NUM, L4_NEU_NUM]))
b_c4 = tf.Variable(b_alpha * tf.random_normal([L4_NEU_NUM]))
conv4 = tf.nn.relu(tf.nn.bias_add(tf.nn.conv2d(conv3, w_c4, strides=[1, 1, 1, 1], padding="SAME"), b_c4))
conv4 = tf.nn.max_pool(conv4, ksize=[1, 2, 2, 1], strides=[1, 2, 2, 1], padding="SAME")
conv4 = tf.nn.dropout(conv4, keep_prob)
# Fully connected layer
r = int(math.ceil(IMAGE_HEIGHT / (2 ** MAX_POOL_NUM)) * math.ceil(IMAGE_WIDTH / (2 ** MAX_POOL_NUM)) * L4_NEU_NUM)
w_d = tf.Variable(w_alpha * tf.random_normal([r, FULL_LAYER_FEATURE_NUM]))
b_d = tf.Variable(b_alpha * tf.random_normal([FULL_LAYER_FEATURE_NUM]))
dense = tf.reshape(conv4, [-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([FULL_LAYER_FEATURE_NUM, 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():
output = crack_captcha_cnn()
# loss = tf.reduce_mean(tf.nn.softmax_cross_entropy_with_logits(output, Y))
loss = tf.reduce_mean(tf.nn.sigmoid_cross_entropy_with_logits(logits=output, labels=Y))
# 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)
accuray = 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, str = get_next_batch(64)
_, loss_ = sess.run([optimizer, loss], feed_dict={X: batch_x, Y: batch_y, keep_prob: 0.75})
print("**", step, loss_, str)
if step % 5 == 0:
batch_x_test, batch_y_test, str = get_next_batch(100)
acc = sess.run(accuray, feed_dict={X: batch_x_test, Y: batch_y_test, keep_prob: 1.})
print(step, acc)
if acc > 0.6:
saver.save(sess, "./crack_captch.model", global_step=step)
break
step += 1
#train_crack_captcha_cnn()
def crack_captcha(captcha_image):
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)
text_list = sess.run(predict, feed_dict={X: [captcha_image], keep_prob: 1})
text = text_list[0].tolist()
vector = np.zeros(MAX_CAPTCHA * CHAR_SET_LEN)
i = 0
for n in text:
vector[i * CHAR_SET_LEN + n] = 1
i += 1
return vec2text(vector)
def crack_captcha2():
output = crack_captcha_cnn()
saver = tf.train.Saver()
with tf.Session() as sess:
saver.restore(sess, tf.train.latest_checkpoint('.'))
n = 1
while n <= 10:
text, image = gen_captch_text_and_image()
image = image.flatten() / 255
predict = tf.argmax(tf.reshape(output, [-1, MAX_CAPTCHA, CHAR_SET_LEN]), 2)
text_list = sess.run(predict, feed_dict={X: [image], keep_prob: 1})
vec = text_list[0].tolist()
predict_text = vec2text(vec)
print("正確:{} 預測:{}".format(text, predict_text))
n += 1
#crack_captcha2()
def main():
text, image = gen_captch_text_and_image()
image = convert2gray(image)
image = image.flatten() / 255
predict_text = crack_captcha(image)
print("正確:{} 預測:{}".format(text, predict_text))
#main()
def run(image_path):
image = Image.open(image_path)
image = convert2gray(image)
image = image.flatten() / 255
predict_text = crack_captcha(image)
return "".join(predict_text)
run(sys.argv[1])