那我来讲解关于“Python入门教程之识别验证码”的攻略。
1. 前言
验证码是目前防止自动化机器人攻击的一种重要方式。而在自动化测试、爬虫等场景下,我们又需要自动识别验证码。因此,学习如何识别验证码也是学习Python的重要一环。
2. 主要技术
本教程将采用Python 3.7版本,涉及到如下技术:
-
图像处理
-
机器学习
-
神经网络
3. 环境和库的准备
首先我们需要准备开发环境,这里我们建议使用Anaconda来安装Python。然后我们需要安装相关库来进行图像处理、机器学习以及神经网络的开发。这里数Python基本的库:NumPy、SciPy等。在机器学习和神经网络的开发中,我们推荐使用tensorflow。
4.验证码的识别过程
验证码的识别主要涉及以下几个步骤:
-
数据集的准备
-
图像预处理
-
训练模型
-
验证码测试
4.1 数据集的准备
为了训练模型,我们需要一个包含验证码的数据集,这里我们可以直接通过网络爬虫爬取,或者通过收集公开数据集来获取。可以通过以下方式获取训练集:
import requests
import os
def save_image(url, filename):
with open(filename, "wb") as f:
f.write(requests.get(url).content)
def download_captcha(count):
for i in range(count):
url = "http://www.example.com/captcha/{0}.png".format(str(i))
filename = os.path.join("captcha", "{0}.png".format(str(i)))
save_image(url, filename)
if __name__ == '__main__':
download_captcha(10000) #下载10000个验证码
4.2 图像预处理
预处理是为了让原始图像更适合机器学习或神经网络算法的处理,预处理中可以包括以下技术:
-
二值化
-
去噪
-
分割
import glob
import cv2
def preprocess_image(image_path):
gray = cv2.imread(image_path, cv2.IMREAD_GRAYSCALE)
gray = cv2.resize(gray, (200, 60))
_, binary = cv2.threshold(gray, 180, 255, cv2.THRESH_BINARY)
kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (3, 3))
binary = cv2.morphologyEx(binary, cv2.MORPH_CLOSE, kernel)
binary = cv2.medianBlur(binary, 3)
return binary
if __name__ == '__main__':
paths = glob.glob(os.path.join("captcha", "*.png"))
for image_path in paths:
binary = preprocess_image(image_path)
cv2.imwrite(os.path.join("captcha_preprocessed", os.path.basename(image_path)), binary)
4.3 训练模型
这里我们使用tensorflow来训练一个卷积神经网络模型(CNN),用于识别验证码:
import tensorflow as tf
import os
def train_cnn():
char_set = ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9']
char_set_len = len(char_set)
input_height, input_width = 60, 200
input_channel = 1
batch_size = 100
epochs = 100
output_node_names = "output"
model_dir = os.path.join("captcha_model", "model.ckpt")
X = tf.placeholder(tf.float32, [None, input_height, input_width, input_channel])
Y = tf.placeholder(tf.float32, [None, char_set_len * 4])
logits = cnn(X, char_set_len)
loss = tf.reduce_mean(tf.nn.sigmoid_cross_entropy_with_logits(logits=logits, labels=Y))
optimizer = tf.train.AdamOptimizer(learning_rate=0.001).minimize(loss)
predict = tf.reshape(logits, [-1, 4, char_set_len])
max_pred = tf.argmax(predict, axis=2)
decoded_pred = tf.reduce_join(tf.transpose(tf.argmax(predict, axis=2), perm=[1, 0]), 1)
saver = tf.train.Saver()
with tf.Session() as session:
session.run(tf.global_variables_initializer())
for epoch in range(epochs):
avg_loss = 0.
total_batch = int(len(X_train) / batch_size)
for i in range(total_batch):
batch_X = X_train[i*batch_size:(i+1)*batch_size]
batch_Y = Y_train[i*batch_size:(i+1)*batch_size]
_, c = session.run([optimizer, loss], feed_dict={X: batch_X, Y: batch_Y})
avg_loss += c / total_batch
print("Epoch:", '%d' % (epoch + 1), "cost=", "{:.9f}".format(avg_loss))
saver.save(session, model_dir)
print("Model saved!")
if __name__ == '__main__':
train_cnn()
4.4 验证码测试
训练好模型后,我们可以用训练好的模型去测试验证码的识别效果了。验证码测试主要步骤如下:
-
从验证码中分割出4个字符
-
对每个字符进行预处理
-
利用模型进行识别
import glob
import cv2
import os
import numpy as np
import tensorflow as tf
def test_captcha():
char_set = ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9']
char_set_len = len(char_set)
input_height, input_width = 60, 200
input_channel = 1
model_dir = os.path.join("captcha_model", "model.ckpt")
X = tf.placeholder(tf.float32, [None, input_height, input_width, input_channel])
logits = cnn(X, char_set_len)
predict = tf.reshape(logits, [-1, 4, char_set_len])
max_pred = tf.argmax(predict, axis=2)
decoded_pred = tf.reduce_join(tf.transpose(tf.argmax(predict, axis=2), perm=[1, 0]), 1)
saver = tf.train.Saver()
with tf.Session() as session:
saver.restore(session, model_dir)
paths = glob.glob(os.path.join("captcha", "*.png"))
for image_path in paths:
image = cv2.imread(image_path, cv2.IMREAD_GRAYSCALE)
_, binary = cv2.threshold(image, 100, 255, cv2.THRESH_BINARY)
contours, hierarchy = cv2.findContours(binary, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)
c_len = len(contours)
if c_len != 4:
print("can't recognize captcha.")
continue
part_digits = []
for j in range(c_len):
x, y, w, h = cv2.boundingRect(contours[j])
part_image = binary[y:y+h, x:x+w]
part_image = cv2.resize(part_image, (input_width, input_height))
part_digits.append(part_image)
part_digits_array = np.array(part_digits) / 255.0
predict_res = session.run(decoded_pred, feed_dict={X: part_digits_array[:, :, :, np.newaxis]})
print(predict_res)
if __name__ == '__main__':
test_captcha()
以上就是关于“Python入门教程之识别验证码”的攻略了。
本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:python入门教程之识别验证码 - Python技术站