「2022 年」崔庆才 Python3 爬虫 - OpenCV图像匹配识别滑动验证码缺口
off999 2024-12-22 20:08 50 浏览 0 评论
上一节我们学习了利用 OCR 技术对图形验证码进行识别的方法,但随着互联网技术的发展,各种新型验证码层出不穷,最具有代表性的便是滑动验证码了。
本节我们首先介绍下滑动验证码的验证流程,然后介绍一个简易的利用图像处理技术来识别滑动验证码缺口的方法。
1. 滑动验证码
说起滑动验证码,比较有代表性的服务商有极验、网易易盾等,验证码效果如图所示:
验证码下方通常会有一个滑轨,同时带有文字提示「拖动滑块完成拼图」,我们需要按住滑轨上的滑块向右拖拽,这时候验证码最左侧的滑块便会跟随滑轨上的滑块向右移动,在验证码右侧会有一个滑块缺口,我们需要恰好将滑块拖动到目标缺口处,这时候就算验证成功了,验证成功的效果如图所示:
所以,如果我们想要用爬虫来自动化完成这一流程的话,关键步骤有如下两个:
- 识别出目标缺口的位置
- 将缺口滑动到对应位置
其中第二步的实现有多种方式,比如我们可以用 Selenium 等自动化工具模拟完成这个流程,验证并登录成功之后获取对应的 Cookies 或 Token 等信息再进行后续的操作,但这种方法运行效率会比较低。另一种方法便是直接逆向验证码背后的 JavaScript 逻辑,将缺口信息直接传给 JavaScript 代码执行获取一些类似“密钥”的信息,再利用这些“密钥”进行下一步的操作。
注意:由于某些出于安全考虑的原因,本书不会再介绍第二步的具体操作,而是只针对于第一步的技术问题进行讲解。
因此,本节只会针对于第一步即如何识别出目标缺口的位置进行介绍,即给定一张验证码图片,如何用图像识别的方法识别出缺口的位置。
2.基本原理
本节我们会介绍利用 OpenCV 进行缺口识别的方法,输入一张带有缺口的验证码图片,输出缺口的位置(一般为缺口左侧横坐标)。
比如输入的验证码图片如下:
最后输出的识别结果如下:
本节介绍的方法是利用 OpenCV 进行基本的图像处理来实现的,主要步骤包括:
- 对验证码图片进行高斯模糊滤波处理,消除部分噪声干扰
- 对验证码图片应用边缘检测算法,通过调整相应阈值识别出滑块边缘
- 对上一步得到的各个边缘轮廓信息,通过对比面积、位置、周长等特征筛选出最可能的轮廓位置,得到缺口位置。
3.准备工作
在本节开始之前请确保已经安装好了 python-opencv 库,安装方式如下:
pip3 install python-opencv如果安装出现问题,可以参考详细的安装步骤:https://setup.scrape.center/python-opencv。
另外建议提前准备一张滑动验证码图片,样例图片下载地址:https://github.com/Python3WebSpider/CrackSlideCaptcha/blob/cv/captcha.png,当然也可以从 https://captcha1.scrape.center/ 自行截取,最终的图片如上文所示。
4.基础知识
在真正开始介绍之前,我们先需要了解一些 OpenCV 的基础 API,以帮助我们更好地理解整个原理。
高斯滤波
高斯滤波是用来去除图像中的一些噪声的,基本效果其实就是把一张图像变得模糊化,减少一些图像噪声干扰,从而为下一步的边缘检测做好铺垫。
OpenCV 提供了一个用于实现高斯模糊的方法,叫做 GaussianBlur,方法声明如下:
def GaussianBlur(src, ksize, sigmaX, dst=None, sigmaY=None, borderType=None)比较重要的参数介绍如下:
- src:即需要被处理的图像。
- ksize:进行高斯滤波处理所用的高斯内核大小,它需要是一个元组,包含 x 和 y 两个维度。
- sigmaX:表示高斯核函数在 X 方向的的标准偏差。
- sigmaY:表示高斯核函数在 Y 方向的的标准偏差,若 sigmaY 为 0,就将它设为 sigmaX,如果 sigmaX 和 sigmaY 都是 0,那么 sigmaX 和 sigmaY 就通过 ksize 计算得出。
这里 ksize 和 sigmaX 是必传参数,对本节样例图片,ksize 我们可以取 (5, 5),sigmaX 可以取 0。
经过高斯滤波处理后,图像会变得模糊,效果如下:
边缘检测
由于验证码目标缺口通常具有比较明显的边缘,所以借助于一些边缘检测算法并通过调整阈值是可以找出它的位置的。目前应用比较广泛的边缘检测算法是 Canny,它是 John F. Canny 于 1986 年开发出来的一个多级边缘检测算法,效果还是不错的,OpenCV 也对此算法进行了实现,方法名称就叫做 Canny,声明如下:
def Canny(image, threshold1, threshold2, edges=None, apertureSize=None, L2gradient=None)比较重要的参数介绍如下:
- image:即需要被处理的图像。
- threshold1、threshold2:两个阈值,分别为最小和最大判定临界点。
- apertureSize:用于查找图像渐变的 Sobel 内核的大小。
- L2gradient:指定用于查找梯度幅度的等式。
通常来说,我们只需要设定 threshold1 和 threshold2 即可,其数值大小需要视不同图像而定,比如本节样例图片可以分别取 200 和 450。
经过边缘检测算法处理后,一些比较明显的边缘信息会被保留下来,效果如下:
轮廓提取
进行边缘检测处理后,我们可以看到图像中会保留有比较明显的边缘信息,下一步我们可以用 OpenCV 将边缘轮廓提取出来,这里需要用到 findContours 方法,方法声明如下:
def findContours(image, mode, method, contours=None, hierarchy=None, offset=None)比较重要的参数介绍如下:
- image:即需要被处理的图像。
- mode:定义轮廓的检索模式,详情见 OpenCV 的 RetrievalModes 的介绍。
- method:定义轮廓的近似方法,详情见 OpenCV 的 ContourApproximationModes 的介绍。
在这里,我们选取 mode 为 RETR_CCOMP,method 为 CHAIN_APPROX_SIMPLE,具体的选型标准可以参考 OpenCV 的文档介绍,这里不再展开讲解。
外接矩形
提取到轮廓之后,为了方便进行判定,我们可以将轮廓的外界矩形计算出来,这样方便我们根据面积、位置、周长等参数进行判定,以得出该轮廓是不是目标滑块的轮廓。
计算外接矩形使用的方法是 boundingRect,方法声明如下:
def boundingRect(array)只有一个参数:
- array:可以是一个灰度图或者 2D 点集,这里可以传入轮廓信息。
经过轮廓信息和外接矩形判定之后,我们可以得到类似如下结果:
可以看到这样就能成功获取各个轮廓的外接矩形,接下来我们根据外接矩形的面积、和位置就能筛选出缺口对应的位置了。
轮廓面积
现在已经得到了各个外接矩形,但是很明显有些矩形不是我们想要的,我们可以根据面积、周长等来进行筛选,这里就需要用到计算面积的方法,叫做 contourArea,方法定义如下:
def contourArea(contour, oriented=None)参数介绍如下:
- contour:轮廓信息。
- oriented:面向区域标识符。有默认值 False。若为 True,该函数返回一个带符号的面积值,正负取决于轮廓的方向(顺时针还是逆时针)。若为 False,表示以绝对值返回。
返回结果就是轮廓的面积。
轮廓周长
同样,周长的计算也有对应的方法,叫做 arcLength,方法定义如下:
def arcLength(curve, closed)参数介绍如下:
- curve:轮廓信息。
- closed:表示轮廓是否封闭。
返回结果就是轮廓的周长。
以上内容介绍了一些 OpenCV 内置方法,了解了这些方法的用法,我们可以对下文的具体实现有更透彻的理解。
5.缺口识别
接下来我们就开始真正实现一下缺口识别算法了。
首先我们定义高斯滤波、边缘检测、轮廓提取的三个方法,实现如下:
import cv2
GAUSSIAN_BLUR_KERNEL_SIZE = (5, 5)
GAUSSIAN_BLUR_SIGMA_X = 0
CANNY_THRESHOLD1 = 200
CANNY_THRESHOLD2 = 450
def get_gaussian_blur_image(image):
return cv2.GaussianBlur(image, GAUSSIAN_BLUR_KERNEL_SIZE, GAUSSIAN_BLUR_SIGMA_X)
def get_canny_image(image):
return cv2.Canny(image, CANNY_THRESHOLD1, CANNY_THRESHOLD2)
def get_contours(image):
contours, _ = cv2.findContours(image, cv2.RETR_CCOMP, cv2.CHAIN_APPROX_SIMPLE)
return contours三个方法介绍如下:
- get_gaussian_blur_image:传入待处理图像信息,返回高斯滤波处理后的图像,ksize 定义为 (5, 5),sigmaX 定义为 0。
- get_canny_image:传入待处理图像信息,返回边缘检测处理后的图像,threshold1 和 threshold2 分别定义为 200 和 450。
- get_contours:传入待处理图像信息,返回检测到的轮廓信息,这里 mode 设定为 RETR_CCOMP,method 设定为 CHAIN_APPROX_SIMPLE。
原始待识别验证码命名为 captcha.png,接下来我们分别调用以上方法对验证码进行处理:
image_raw = cv2.imread('captcha.png')
image_height, image_width, _ = image_raw.shape
image_gaussian_blur = get_gaussian_blur_image(image_raw)
image_canny = get_canny_image(image_gaussian_blur)
contours = get_contours(image_canny)原始图片我们命名为 image_raw 变量,读取图片之后获取其宽高像素信息,接着调用了 get_gaussian_blur_image 方法进行高斯滤波处理,返回结果命名为 image_gaussian_blur,接着将 image_gaussian_blur 传给 get_canny_image 方法进行边缘检测处理,返回结果命名为 image_canny,接着调用 get_contours 方法得到各个边缘的轮廓信息,赋值为 contours 变量。
好,得到各个轮廓信息之后,我们便需要根据各个轮廓的外接矩形的面积、周长、位置来筛选我们想要结果了。
所以,我们需要先确定怎么来筛选,比如面积我们可以设定一个范围,周长设定一个范围,缺口位置设定一个范围,通过实际测量,我们可以得出目标缺口的外接矩形的高度大约是验证码高度的 0.25 倍,宽度大约是验证码宽度的 0.15 倍。在允许误差 20% 的情况下,根据验证码的宽高信息我们大约可以计算出面积、周长的范围,同时缺口位置(缺口左侧)也有一个最小偏移值,比如最小偏移是验证码宽度的 0.2 倍,最大偏移是验证码宽度的 0.85 倍。综合这些内容,我们可以定义三个阈值方法:
def get_contour_area_threshold(image_width, image_height):
contour_area_min = (image_width * 0.15) * (image_height * 0.25) * 0.8
contour_area_max = (image_width * 0.15) * (image_height * 0.25) * 1.2
return contour_area_min, contour_area_max
def get_arc_length_threshold(image_width, image_height):
arc_length_min = ((image_width * 0.15) + (image_height * 0.25)) * 2 * 0.8
arc_length_max = ((image_width * 0.15) + (image_height * 0.25)) * 2 * 1.2
return arc_length_min, arc_length_max
def get_offset_threshold(image_width):
offset_min = 0.2 * image_width
offset_max = 0.85 * image_width
return offset_min, offset_max三个方法介绍如下:
- get_contour_area_threshold:定义目标轮廓的下限和上限面积,分别为 contour_area_min 和 contour_area_max。
- get_arc_length_threshold:定义目标轮廓的下限和上限周长,分别为 arc_length_min 和 arc_length_max。
- get_offset_threshold:定义目标轮廓左侧的下限和上限偏移量,分别为 offset_min 和 offset_max。
最后我们只需要遍历各个轮廓信息,根据上述限定条件进行筛选,最后得出目标轮廓信息即可,实现如下:
contour_area_min, contour_area_max = get_contour_area_threshold(image_width, image_height)
arc_length_min, arc_length_max = get_arc_length_threshold(image_width, image_height)
offset_min, offset_max = get_offset_threshold(image_width)
offset = None
for contour in contours:
x, y, w, h = cv2.boundingRect(contour)
if contour_area_min < cv2.contourArea(contour) < contour_area_max and \
arc_length_min < cv2.arcLength(contour, True) < arc_length_max and \
offset_min < x < offset_max:
cv2.rectangle(image_raw, (x, y), (x + w, y + h), (0, 0, 255), 2)
offset = x
cv2.imwrite('image_label.png', image_raw)
print('offset', offset)这里我们首先调用了 get_contour_area_threshold、get_arc_length_threshold、get_offset_threshold 方法获取了轮廓的判定阈值,然后遍历了 contours 根据这些阈值进行了筛选,最终得到的外接矩形的 x 值就是目标缺口的偏移量。
同时目标缺口的外接矩形我们也调用了 rectangle 方法进行了标注,最终将其保存为 image_label.png 图像。
最终运行结果如下:
offset 163同时得到输出的 image_label.png 文件如下:
这样我们就成功提取出来了目标滑块的位置了,本节的问题得以解决。
注意:出于安全考虑,本书只针对于第一步 - 识别验证码缺口位置的的技术问题进行讲解,关于怎样去模拟滑动或者绕过验证码,本书不再进行介绍,可以自行搜索相关资料探索。
6. 总结
本节我们介绍了利用 OpenCV 来识别滑动验证码缺口的方法,其中涉及到了一些关键的图像处理和识别技术,如高斯模糊、边缘检测、轮廓提取等算法。了解了基本的图像识别技术后,我们可以举一反三,将其应用到其他类型的工作上,也会很有帮助。
本节代码:https://github.com/Python3WebSpider/CrackSlideCaptcha/tree/cv,注意这里是 cv 分支。
相关推荐
- itunes下载的固件在哪个位置
-
可以刷机的将手机联入电脑电脑会自动下载符合手机的版本的固件是一样的,都是通过官方固件包来重装系统。操作步骤如下;1.电脑端下载最新版本的itunes,不然重装时可能会造成未知错误。2.iphone...
- 电脑重装系统后没声音(电脑重装系统后没声音怎么解决win7)
-
如果您在电脑重装系统后没有声音,可能是由于以下一些常见问题导致的:1.驱动程序问题:重装系统后,可能需要重新安装声卡驱动程序。您可以从电脑制造商的官方网站或声卡制造商的官方网站上下载并安装最新的声卡驱...
- win10制作系统u盘(制作win10系统优盘)
-
方法一:使用微软官方工具制作u盘工具安装win101、首先电脑浏览器输入“windows10下载”,找到微软官方地址进入,然后选择立即下载工具到电脑上。2、鼠标右键选择以管理员身份运行,同意协议进入下...
- 苹果手机wlan设置在哪(苹果手机 wlan)
-
进入设置->Wi-Fi。如何设置iPhone的WIFI?2.选择Wi-Fi之后,会显示附近能搜索到的所有的Wi-Fi网络。如何设置iPhone的WIFI?3.选中其中网络Wi-F...
- 召唤系统游戏(召唤系统游戏排行)
-
亡灵进化专家:写的很不错了。猪脚可以用金属或骨头帮自己的亡灵进化升级挺有意思的。不过还没写完网游之审判:是英雄无敌类型的。不过写的很牛逼也写完了。推荐看看还有不死传说:虽然不是召唤的,主教是僵尸和吸血...
- w7系统怎么样(电脑w7系统怎么样)
-
有以下几点理由来分析为什么win7受欢迎1、Windows7有望受到企业用户认可微软目前的最大担心是:企业用户认为Windows7性能同Vista相差不大,因此不会出手购买。微软当初发布Vist...
- 无敌系统流小说(无敌系统流的小说)
-
《嫡女之花开富贵》作者:伊人睽睽简介祖父是镇国将军,贵不可言;外公是帝师,才名满天下;父母亲琴瑟和鸣,恩爱无双,无妾室插足;穿越为书香门第的嫡小姐,且无任何庶兄妹,慕兰音认为,她这一生,必将佳期如梦...
-
- 键盘上windows键是哪个键(电脑键盘上windows键是哪个)
-
一、台式机键盘。Windows键,简称“Winkey”或“Win键”,是在计算机键盘左下角Ctrl和Alt键之间的按键,台式机全尺寸键盘的主键盘区左下角和右下角各有一个,图案是MicrosoftWindows的视窗徽标。二、笔记...
-
2026-01-13 11:51 off999
-
- 桌面图标设置在哪打开(桌面图标从哪里调出)
-
1、首先来到电脑桌面,此时桌面没有任何图标,如下图所示。2、我们先右键单击任务栏,会出现工具栏,这时我们在下拉的选项里选择“快速启动”按钮。3、单击快速启动按钮后会出现如图所示情况,这时在电脑屏幕的左下方会显示很多快捷按钮,一般情况下单击快...
-
2026-01-13 10:51 off999
- windows如何进入启动项(怎么进入启动选项)
-
方法步骤如下:1.点击应用在Windows设置界面点击应用选项进入。2.选择启动在左侧分类中选择启动选项。3.点击开关点击软件后方的开关即可启动或关闭开机启动项。1、在Window的文件资...
- win11下载安装
-
一、允许安装软件1、首先点击左下角的开始按键,然后点击“settings”进入设置。2、然后点击设置中的“应用”选项。3、在点击左侧任务栏中的“应用和功能”。4、点击下拉栏,然后选择其中的“任何来源”...
- win7支持的最高配置(win7支持的最高配置是多少)
-
答案是支持win7的最高配置应该是i99900k加b365主板。 不过这套配置市面上价格偏高。这种机器比同等酷睿13代处理器的价格还要高至少一千元以上。而且就性能而言要超过i99900...
- 指令引用的内存不能为read(指令引用的0x0000000内存.该内存不能为read)
-
出现“指令引用内存不能为read”的错误可能有多种原因,包括软件冲突、驱动问题、内存质量问题等。以下是一些可能的解决方案:1.检查是否有软件冲突:尝试关闭可能冲突的软件,例如杀毒软件、优化软件等。2...
- hp1010打印机驱动程序(hp deskjet1010打印机驱动)
-
1.把光盘到电脑里然后打开光盘找到“setup.exe”双击运行。2.这里点击“不用了,谢谢,我喜欢CD安装”;下载的驱动也点这个。3.到这个一步有6个软件需要安装,不用点选直接下一步即可。4.同意服...
欢迎 你 发表评论:
- 一周热门
-
-
抖音上好看的小姐姐,Python给你都下载了
-
全网最简单易懂!495页Python漫画教程,高清PDF版免费下载
-
飞牛NAS部署TVGate Docker项目,实现内网一键转发、代理、jx
-
Python 3.14 的 UUIDv6/v7/v8 上新,别再用 uuid4 () 啦!
-
python入门到脱坑 输入与输出—str()函数
-
宝塔面板如何添加免费waf防火墙?(宝塔面板开启https)
-
Python三目运算基础与进阶_python三目运算符判断三个变量
-
(新版)Python 分布式爬虫与 JS 逆向进阶实战吾爱分享
-
失业程序员复习python笔记——条件与循环
-
系统u盘安装(win11系统u盘安装)
-
- 最近发表
- 标签列表
-
- python计时 (73)
- python安装路径 (56)
- python类型转换 (93)
- python进度条 (67)
- python吧 (67)
- python的for循环 (65)
- python格式化字符串 (61)
- python静态方法 (57)
- python列表切片 (59)
- python面向对象编程 (60)
- python 代码加密 (65)
- python串口编程 (77)
- python封装 (57)
- python写入txt (66)
- python读取文件夹下所有文件 (59)
- python操作mysql数据库 (66)
- python获取列表的长度 (64)
- python接口 (63)
- python调用函数 (57)
- python多态 (60)
- python匿名函数 (59)
- python打印九九乘法表 (65)
- python赋值 (62)
- python异常 (69)
- python元祖 (57)
