Python简单验证码识别的实现过程
什么是验证码识别
验证码识别是指通过计算机自动识别验证码的过程。验证码通常是由数字和字母组成的一串字符,在网站注册、登陆、评论等操作中,是为了防止恶意软件、自动程序和机器人等不法行为而设置的一道安全关卡。但是在一些情况下,我们需要使用自动化程序来进行批量操作,如数据爬取、自动注册等。这时候就需要通过计算机来自动识别验证码。
实现过程
针对简单的验证码,如数字字符、字母字符和简单的图形验证,我们可以通过使用Python编程语言来实现自动识别验证码的过程。这里我们以数字字符验证码为例进行介绍。
数字字符验证码通常由几个数字字符组成,图片的背景为白色或其他颜色,数字字符为黑色或其他颜色。我们可以通过以下步骤来对数字字符验证码进行识别:
将图片转换为灰度图像
对图像进行二值化
对图像进行膨胀和腐蚀处理
对图像进行轮廓检测
将轮廓进行筛选
使用机器学习算法进行数字字符识别
下面我们一步一步来介绍这些步骤的具体实现方法。
将图片转换为灰度图像
使用Python的OpenCV库来实现将图片转换为灰度图像的过程:
import cv2
img = cv2.imread('captcha.png')
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
cv2.imshow('image', gray)
cv2.waitKey(0)
cv2.destroyAllWindows()
cv2.cvtColor()函数是将图片从一种颜色空间转换为另一种颜色空间的函数,第一个参数是输入的图片,第二个参数是颜色转换的方式。这里我们使用的是BGR2GRAY,即将图片从BGR色彩空间转换为灰度色彩空间。返回的gray是灰度图像。
对图像进行二值化
使用Python的OpenCV库来实现对图像进行二值化的过程:
import cv2
img = cv2.imread('captcha.png')
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
# 对灰度图像进行二值化处理
_, binary = cv2.threshold(gray, 127, 255, cv2.THRESH_BINARY)
cv2.imshow('image', binary)
cv2.waitKey(0)
cv2.destroyAllWindows()
cv2.threshold()函数是将图像进行二值化的函数,第一个参数是输入的图片,第二个参数是设置阈值,像素值大于阈值的被设置为一,小于阈值的被设置为零。第三个参数是设置二值化的最大值,一般为255。第四个参数是设置阈值的方式,有多个选项,这里我们将使用THRESH_BINARY方式,即二值化时黑白两色。
对图像进行膨胀和腐蚀处理
使用Python的OpenCV库来实现对图像进行膨胀和腐蚀处理的过程:
import cv2
import numpy as np
img = cv2.imread('captcha.png')
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
_, binary = cv2.threshold(gray, 127, 255, cv2.THRESH_BINARY)
kernel = np.ones((3, 3), np.uint8)
dilation = cv2.dilate(binary, kernel, iterations=1)
erosion = cv2.erode(dilation, kernel, iterations=1)
cv2.imshow('image', erosion)
cv2.waitKey(0)
cv2.destroyAllWindows()
cv2.dilate()函数是将图像进行膨胀处理的函数,第一个参数是输入的图片,第二个参数是卷积核,用于对像素点进行卷积操作,可以理解为一种模板,用来扫描输入图像的每个像素值,并用相邻像素的最大值来替代该像素值。第三个参数是卷积核的大小,通常为正方形,这里定义的是3x3的正方形卷积核。返回的dilation是膨胀后的图像。
cv2.erode()函数是将图像进行腐蚀处理的函数,与膨胀函数相反,它用相邻像素的最小值来替代该像素值。这里的iterations参数是设置膨胀和腐蚀的迭代次数。
对图像进行轮廓检测
使用Python的OpenCV库来实现对图像进行轮廓检测的过程:
import cv2
import numpy as np
img = cv2.imread('captcha.png')
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
_, binary = cv2.threshold(gray, 127, 255, cv2.THRESH_BINARY)
kernel = np.ones((3, 3), np.uint8)
dilation = cv2.dilate(binary, kernel, iterations=1)
erosion = cv2.erode(dilation, kernel, iterations=1)
contours, hierarchy = cv2.findContours(erosion, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)
cv2.drawContours(img, contours, -1, (0, 255, 0), 2)
cv2.imshow('image', img)
cv2.waitKey(0)
cv2.destroyAllWindows()
cv2.findContours()函数是用来在二值化的图像中查找轮廓的函数,第一个参数是输入的图像,第二个参数是定义轮廓的检索模式,有多个选项,这里我们将使用RETR_TREE模式,即检测到的轮廓之间建立层级关系。第三个参数是定义轮廓的近似方法,有多个选项,这里我们将使用CHAIN_APPROX_SIMPLE方式,即只保留轮廓的拐点信息,将轮廓图像压缩为一个拐点序列,以便于存储。
cv2.drawContours()函数是绘制轮廓图像的函数,第一个参数是目标图像,第二个参数是轮廓列表,第三个参数是轮廓的索引,这里设置为-1表示绘制所有轮廓,第四个参数是线条颜色,第五个参数是线条粗细。
将轮廓进行筛选
使用Python的OpenCV库来实现将轮廓进行筛选的过程:
import cv2
import numpy as np
img = cv2.imread('captcha.png')
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
_, binary = cv2.threshold(gray, 127, 255, cv2.THRESH_BINARY)
kernel = np.ones((3, 3), np.uint8)
dilation = cv2.dilate(binary, kernel, iterations=1)
erosion = cv2.erode(dilation, kernel, iterations=1)
contours, hierarchy = cv2.findContours(erosion, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)
for cnt in contours:
area = cv2.contourArea(cnt)
if area < 100:
continue
x, y, w, h = cv2.boundingRect(cnt)
cv2.rectangle(img, (x, y), (x + w, y + h), (0, 255, 0), 2)
cv2.imshow('image', img)
cv2.waitKey(0)
cv2.destroyAllWindows()
在找到轮廓后,我们需要对轮廓进行筛选,只保留面积大于一定值的轮廓,这里设定面积为100。在保留的轮廓中,使用cv2.boundingRect()函数,将轮廓外接矩形的左上角的坐标、宽度和高度计算出来,并用cv2.rectangle()函数绘制矩形框。
使用机器学习算法进行数字字符识别
使用Python的机器学习库scikit-learn来实现数字字符识别的过程:
import cv2
import numpy as np
from sklearn.externals import joblib
img = cv2.imread('captcha.png')
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
_, binary = cv2.threshold(gray, 127, 255, cv2.THRESH_BINARY)
kernel = np.ones((3, 3), np.uint8)
dilation = cv2.dilate(binary, kernel, iterations=1)
erosion = cv2.erode(dilation, kernel, iterations=1)
contours, hierarchy = cv2.findContours(erosion, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)
captcha_model = joblib.load('captcha_model.m')
for cnt in contours:
area = cv2.contourArea(cnt)
if area < 100:
continue
x, y, w, h = cv2.boundingRect(cnt)
roi = binary[y:y + h, x:x + w]
roi = cv2.resize(roi, (20, 20))
roi = np.reshape(roi, (1, -1))
result = captcha_model.predict(roi)
cv2.rectangle(img, (x, y), (x + w, y + h), (0, 255, 0), 2)
cv2.putText(img, str(result[0]), (x, y - 5), cv2.FONT_HERSHEY_SIMPLEX, 1, (0, 255, 0), 2)
cv2.imshow('image', img)
cv2.waitKey(0)
cv2.destroyAllWindows()
scikit-learn是Python的机器学习库,我们可以使用它来训练数字字符分类器,将训练好的模型保存,再用来对验证码进行识别。
这里是使用scikit-learn库训练数字字符分类器和保存模型的过程:
import cv2
import numpy as np
from sklearn.externals import joblib
from sklearn.neighbors import KNeighborsClassifier
data = []
target = []
for i in range(10):
for j in range(50):
img = cv2.imread('digits/%d/%d.png' % (i, j), 0)
img = cv2.resize(img, (20, 20))
img = np.reshape(img, (1, -1))
data.append(img)
target.append(i)
data = np.squeeze(np.array(data))
target = np.array(target)
captcha_model = KNeighborsClassifier(n_neighbors=3)
captcha_model.fit(data, target)
joblib.dump(captcha_model, 'captcha_model.m')
在训练好模型后,我们可以通过joblib.load()函数来加载这个模型,然后将验证码图片中的每个字符提取出来,通过captcha_model.predict()函数,将每个字符进行分类,最后在矩形框上面使用cv2.putText()函数,将识别结果输出。
总结
本文介绍了如何使用Python编程语言对数字字符验证码进行识别的过程。验证码识别是一项复杂的技术,不同的验证码类型需要用不同的识别方法来解决。对于一些简单的验证码,我们可以使用OpenCV库和scikit-learn库来实现自动识别。这里只是对数字字符验证码做了一个简单的演示,不足以适用于复杂的验证码,但对初学者来说,可以作为一个良好的入门案例。