python简单验证码识别的实现过程

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库来实现自动识别。这里只是对数字字符验证码做了一个简单的演示,不足以适用于复杂的验证码,但对初学者来说,可以作为一个良好的入门案例。

后端开发标签