OpenCV破解腾讯滑块验证码:模板匹配与轮廓检测实战
本文详细解析如何利用OpenCV破解腾讯滑块验证码。通过Python实现两种核心算法:基于模板匹配的缺口识别(准确率约50%-90%)和基于轮廓检测的高精度方案(准确率95%以上)。文章涵盖环境配置、图像预处理、API调用及Selenium模拟拖动,并探讨背景透明化与轨迹算法优化等遗留问题。
前言
前言
废话
滑块验证码的自动化破解一直是图像处理领域的热门课题,鉴于众多网站广泛采用此类验证机制,笔者在修改论文的间隙完成了相关研究。实现这一目标离不开高效的图像处理技术,而OpenCV-Python无疑是首选工具。尽管笔者对P.S.两天速成不敢保证代码质量掌握尚浅,但欢迎直接指出代码或逻辑中的问题,无需客套。
环境配置
环境
首先需准备Python运行环境,并安装OpenCV对应的Python库,具体安装命令如下:
pip install opencv-python
随后进行可用性测试,代码示例如下:
import cv2 as cv
import numpy as np
if __name__ == '__main__':
img = np.ones((200, 200, 3), np.uint8) * 255
cv.rectangle(img, (50, 50), (150, 150), (0, 0, 255), 2)
cv.imshow('test', img)
cv.waitKey(0)
cv.destroyAllWindows()
若配置正确,终端将输出如下提示信息:

OpenCV基础使用
OpenCV的使用
相关API的使用过程伴随大量查阅工作,初期操作较为生疏。建议读者通过官方文档或搜索引擎自行熟悉常用方法,此处不再赘述基础用法。
腾讯滑块验证码破解原理
实现原理及方法
腾讯滑块验证
本次研究的目标是腾讯滑块验证码,调用该接口的网站数量众多,例如知名的在线绘图平台ProcessOn。其滑块验证界面通常包含滑块图片和带有缺口的背景图片,结构类似如下:

通过抓包分析可知,服务器仅返回滑块图片和带有缺口的背景图片,具体数据如下:

破解滑块验证码的核心在于找到滑块缺口的位置。确定缺口位置后,即可利用Selenium模拟拖动滑块至指定坐标以完成验证。传统方法将完整图的像素点和带缺口图的像素点进行比较从而得到缺口位置通过对比完整图与缺口图的像素差异来定位,但现代验证码通常不直接提供完整图,因此必须在带有缺口的图片上进行处理。本文提出两种缺口识别方案:一种基于模板匹配,另一种基于轮廓检测,后续将分别详述。
方案一:模板匹配识别缺口
模板匹配识别缺口
具体实现步骤如下:
1.处理滑块的图片
- 灰度化滑块图片
- 处理一下滑块图中滑块的外圈
- 使用inRange二值化滑块图
- 使用开运算去除白色噪点
运行结果如下所示(左侧为原始滑块,右侧为处理后的滑块):

2.处理带缺口的图片
- 先来个高斯滤波去噪
- 灰度化带缺口图
- 使用阈值二值化该图
运行结果如下所示(左侧为原始图,右侧为处理后的图):

3.进行模板匹配
调用模板匹配API并圈出匹配上的区域,结果如下所示:

警告警告警告
这种方法的缺口识别率在50%左右,很大一部分原因是滑块图的背景为纯白色,这在匹配时会产生很大的干扰,要是能将滑块图的背景变为透明,正确的匹配率可以达到90%以上
如果大家有任何将滑块图的背景变为透明的办法,可以留言到评论区,我真的万分感谢!!!下面是现阶段的实现代码:
# encoding:utf-8
import cv2 as cv
import numpy as np
# 对滑块进行二值化处理
def handle_img1(image):
kernel = np.ones((8, 8), np.uint8) # 去滑块的前景噪声内核
gray = cv.cvtColor(image, cv.COLOR_BGR2GRAY)
width, heigth = gray.shape
for h in range(heigth):
for w in range(width):
if gray[w, h] == 0:
gray[w, h] = 96
# cv.imshow('gray', gray)
binary = cv.inRange(gray, 96, 96)
res = cv.morphologyEx(binary, cv.MORPH_OPEN, kernel) # 开运算去除白色噪点
# cv.imshow('res', res)
return res
# 模板匹配(用于寻找缺口有点误差)
def template_match(img_target, img_template):
tpl = handle_img1(img_template) # 误差来源就在于滑块的背景图为白色
blurred = cv.GaussianBlur(img_target, (3, 3), 0) # 目标图高斯滤波
gray = cv.cvtColor(blurred, cv.COLOR_BGR2GRAY)
ret, target = cv.threshold(gray, 127, 255, cv.THRESH_BINARY) # 目标图二值化
# cv.imshow("template", tpl)
# cv.imshow("target", target)
method = cv.TM_CCOEFF_NORMED
width, height = tpl.shape[:2]
result = cv.matchTemplate(target, tpl, method)
min_val, max_val, min_loc, max_loc = cv.minMaxLoc(result)
left_up = max_loc
right_down = (left_up[0] + height, left_up[1] + width)
cv.rectangle(img_target, left_up, right_down, (0, 0, 255), 2)
cv.imshow('res', img_target)
if __name__ == '__main__':
img0 = cv.imread('./demo/3/hycdn_3.jpg')
img1 = cv.imread('./demo/3/hycdn_3_2.png')
template_match(img0, img1)
cv.waitKey(0)
cv.destroyAllWindows()
方案二:轮廓检测识别缺口
轮廓检测识别缺口
基于轮廓检测缺口的思路简单很多,加上合理的条件识别率在95%以上,实现过程如下:
带缺口图高斯模糊去噪用(200,400)的阈值做Canny边缘检测寻找轮廓对已有的轮廓做约束,比如轮廓的面积范围,轮廓的周长范围
多个匹配结果如下:




实现代码如下:
# encoding:utf-8
import cv2 as cv
def get_pos(image):
blurred = cv.GaussianBlur(image, (5, 5), 0)
canny = cv.Canny(blurred, 200, 400)
contours, hierarchy = cv.findContours(canny, cv.RETR_EXTERNAL, cv.CHAIN_APPROX_SIMPLE)
for i, contour in enumerate(contours):
M = cv.moments(contour)
if M['m00'] == 0:
cx = cy = 0
else:
cx, cy = M['m10'] / M['m00'], M['m01'] / M['m00']
if 6000 < cv.contourArea(contour) < 8000 and 370 < cv.arcLength(contour, True) < 390:
if cx < 400:
continue
x, y, w, h = cv.boundingRect(contour) # 外接矩形
cv.rectangle(image, (x, y), (x + w, y + h), (0, 0, 255), 2)
cv.imshow('image', image)
return x
return 0
if __name__ == '__main__':
img0 = cv.imread('./demo/4/hycdn_4.jpg')
get_pos(img0)
cv.waitKey(0)
cv.destroyAllWindows()
遗留问题与优化方向
遗留问题
问题1
如何将滑块图的纯白背景变为透明背景?
问题2
使用Selenium和轨迹算法拖动滑块时将滑块拖出左侧的范围之外,轨迹算法是先加速后减速整体是向前移动的,按道理来说不可能往回走,但是模拟拖动的时候会出现滑块向后拖动且拖出范围的现象,这问题如何解决?

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持本站。
本站声明
本文内容仅供参考,不代表本站观点。转载或引用请注明出处。如发现内容问题,请通过联系我们页面反馈。













