滑块验证码的识别
前言一、滑块验证码的形式二、采用的方法1.滑块图、背景图切分2.模板匹配总结前言
最近在一个比价的公司实习,公司里面主要使用爬虫来获取一件商品在其他平台的价格。但是在大部分的时候别的平台不愿意把价格数据直接给你,他们会进行一些反爬的手段。例如使用验证码。验证码有很多的类型,今天主要来说说遇到的滑块验证码的识别。
一、滑块验证码的形式
滑块验证码的形式也很多,大多都类似下面这样的。一般类似这样的验证码已经有很成熟的解决方案了。比如js破解,图像识别破解等等。但是我在项目中遇到的验证码有一点不同是下面这种验证码(拼夕夕的验证码)可以看到背景更复杂,而且它使用两个缺口,两个缺口的形状不一样,因此对于此类验证码识别更加困难。
二、采用的方法
对该类新型验证码分析,最开始准备使用深度学习的方法,大力出奇迹,但是有一个现实问题没多少数据。公司目前收集的也只有六七十张,于是只好放弃深度学习,采用传统方法opencv来做。使用opencv做的思路就是,获取滑块图和背景图,进行模板匹配,匹配度最高作为结果输出
1.滑块图、背景图切分
想要拿到干净的滑块图和背景图需要进行js破解,这个破解比较耗时一张验证码大概需要30s,30s后验证码都失效了,所以我只能手动切图。下面是切图代码:
def crop(img_name):img = cv2.imread(img_name)# bg = img[130:,0:362] # 裁剪坐标为[y0:y1, x0:x1]part = img[0:362,0:139]bg = img[0:362,139:]# cv2.imwrite("part_crop.png", part)# cv2.imwrite("bg_crop.png", bg)return bg,part
切好的滑块图和背景图
图片切好过后就可以进行模板匹配了
2.模板匹配
对切好的图片先进行轮廓提取,然后再使用模板匹配,其中轮廓提取使用了Canny算子:
def detect_captcha_gap(bg,tp):'''bg: 背景图片tp: 缺口图片return:空缺距背景图左边的距离'''# 读取背景图片和缺口图片# bg_img = cv2.imread(bg) # 背景图片# tp_img = cv2.imread(tp) # 缺口图片bg_img = bgtp_img = tp# 识别图片边缘bg_edge = cv2.Canny(bg_img, 100, 200)tp_edge = cv2.Canny(tp_img, 100, 200)# 转换图片格式bg_pic = cv2.cvtColor(bg_edge, cv2.COLOR_GRAY2RGB)tp_pic = cv2.cvtColor(tp_edge, cv2.COLOR_GRAY2RGB)# cv2.imwrite("bg_style.png",bg_pic) # 保存背景轮廓提取# cv2.imwrite("slide_style.png",tp_pic) # 保存滑块背景提取# 缺口匹配res = cv2.matchTemplate(bg_pic, tp_pic, cv2.TM_CCOEFF_NORMED)min_val, max_val, min_loc, max_loc = cv2.minMaxLoc(res) # 寻找最优匹配th, tw = tp_pic.shape[:2]tl = max_loc # 左上角点的坐标# 返回缺口的左上角X坐标br = (tl[0]+tw,tl[1]+th) # 右下角点的坐标cv2.rectangle(bg_img, tl, br, (0, 0, 255), 2) # 绘制矩形cv2.imwrite("result_new.png", bg_img) # 保存在本地# 返回缺口的左上角X坐标return tl[0]
下面是Canny算子提取的轮廓图,可以发现效果还是不错,能够看到两幅图中的相似轮廓。
模板匹配的结果
目前已经能够正确匹配出滑块对应缺口的位置了。
总结
做完这个项目发现即使在深度学学习迅猛发展的今天,传统视觉仍然有巨大的作用。