概述:文本对旋转验证码进行了突破及讲述了实现原理,代码使用纯算法 OpenCV,使用代价较小同时不用安装一大堆AI训练相关的模组,方便且能够快速上手
当前亲自验证了能够支持的网站:国内知名短视频平台、海外版 以及 某东等等使用了旋转验证码的网站
基本上是旋转验证码的网站都能过,测试成功率在 99% 以上
实现步骤:
一、下载图片
为了兼容,在这里可以支持自己传base64,或者自己传链接来下载图片
def request_image_content(image_url, proxies: Optional[dict] = None):
"""
图片下载
:param image_url:
:param proxies:
:return:
"""
import requests # type: ignore
headers = {
"user-agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 "
"(KHTML, like Gecko) Chrome/108.0.0.0 Safari/537.36"
}
response = requests.get(image_url, headers=headers, proxies=proxies)
return response.content
def image_to_cv2(base_image: str, image_type: int, grayscale: bool, proxies=None):
"""
根据 图片类型来读取图片数据
:param base_image:
:param image_type:
:param grayscale:
:param proxies:
:return:
"""
assert image_type in [0, 1, 2]
if image_type == 0:
search_base64 = re.search("base64,(.*?)$", base_image)
base64_image = search_base64.group(1) if search_base64 else base_image
image_array = np.asarray(
bytearray(base64.b64decode(base64_image)), dtype="uint8"
)
image = cv2.imdecode(image_array, cv2.IMREAD_COLOR)
elif image_type == 1:
image_content = request_image_content(base_image, proxies)
if not image_content:
raise Exception("请求图片链接失败!")
image_array = np.array(bytearray(image_content), dtype=np.uint8)
image = cv2.imdecode(image_array, cv2.IMREAD_COLOR)
else:
image = cv2.imread(base_image)
if grayscale:
image = cv2.cvtColor(image, cv2.COLOR_RGB2GRAY)
return image
二、识别图像像素相似度
核心原理:使用opencv对两张图片进行合并,同时从0度开始,一点点旋转,选择像素相似度最高的一个度数
步骤1:将外圈图与内圈图的边缘像素进行匹配,获取相似度
mat_rotate = cv2.getRotationMatrix2D((h * 0.5, w * 0.5), rtype * angle, 1)
dst = cv2.warpAffine(inner_image, mat_rotate, (h, w))
ret = cv2.matchTemplate(outer_image, dst, cv2.TM_CCOEFF_NORMED)
similar_value = cv2.minMaxLoc(ret)[1]
步骤2:将相似度最高的一个结果进行返回并输出
step作为步长,设置1则1度1度的旋转,会更加精准
step = 1
rotate_info_list = [RotateData(0, 0, 1, 361, step)]
for item in rotate_info_list:
min_similar_rotate_info = item
for angle in range(*item[2:]):
mat_rotate = cv2.getRotationMatrix2D((h * 0.5, w * 0.5), rtype * angle, 1)
dst = cv2.warpAffine(inner_image, mat_rotate, (h, w))
ret = cv2.matchTemplate(outer_image, dst, cv2.TM_CCOEFF_NORMED)
similar_value = cv2.minMaxLoc(ret)[1]
if similar_value < min_similar_rotate_info.similar:
continue
rotate_info = RotateData(similar_value, angle, angle - step, angle + step, step)
rotate_info_list.append(rotate_info)
if len(rotate_info_list) > 5:
rotate_info_list.remove(min_similar_rotate_info)
min_similar_rotate_info = min(rotate_info_list)
三、效果展示:
输入图片:
输出图片:
核心的步骤及思路提供了,剩下的交给大家了,如果需要源码的话欢迎私聊