skuukzky
文章9
标签0
分类2

文章分类

极验4九宫格

极验4九宫格

极验九宫格

过程

训练是根据 github 的一个库ClassificationCaptchaOcr 进行的,发布不久,原理就是加载预训练模型 resnet18,进行分类训练。

附上他的原理.

1
2
3
我们可以把每张图片都切出来,然后用CNN提取图像特征
选用resnet18,再用相似度对比函数对比小图和九张大图的相似度,选出相似度最大的3张就可以了
因为给了小图,而不是文字,所以我们的特征提取的模型同样可以识别未出现的分类

验证码长这个样子

我们请求网络图片,然后根据返回内容解析,我大概爬了 200 张左右。然后根据图片文件夹切割

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
import os
import secrets
from PIL import Image, ImageFont, ImageDraw, ImageOps
from io import BytesIO


def convert_png_to_jpg(png_bytes: bytes) -> bytes:
    # 将传入的 bytes 转换为图像对象
    png_image = Image.open(BytesIO(png_bytes))

    # 创建一个 BytesIO 对象,用于存储输出的 JPG 数据
    output_bytes = BytesIO()

    # 检查图像是否具有透明度通道 (RGBA)
    if png_image.mode == 'RGBA':
        # 创建白色背景
        white_bg = Image.new("RGB", png_image.size, (255, 255, 255))
        # 将 PNG 图像粘贴到白色背景上,透明部分用白色填充
        white_bg.paste(png_image, (0, 0), png_image)
        jpg_image = white_bg
    else:
        # 如果图像没有透明度,直接转换为 RGB 模式
        jpg_image = png_image.convert("RGB")

    # 将转换后的图像保存为 JPG 格式到 BytesIO 对象
    jpg_image.save(output_bytes, format="JPEG")

    # 返回保存后的 JPG 图像的 bytes
    return output_bytes.getvalue()


def crop_image(image_bytes, coordinates):
    img = Image.open(BytesIO(image_bytes))
    width, height = img.size
    grid_width = width // 3
    grid_height = height // 3
    cropped_images = []
    for coord in coordinates:
        y, x = coord
        left = (x - 1) * grid_width
        upper = (y - 1) * grid_height
        right = left + grid_width
        lower = upper + grid_height
        box = (left, upper, right, lower)
        cropped_img = img.crop(box)
        cropped_images.append(cropped_img)
    return cropped_images


if __name__ == "__main__":
    # 切割顺序,这里是从左到右,从上到下[x,y]
    coordinates = [
        [1, 1],
        [1, 2],
        [1, 3],
        [2, 1],
        [2, 2],
        [2, 3],
        [3, 1],
        [3, 2],
        [3, 3],
    ]

    dir_path = r'/Users/jiangxia/PycharmProjects/pythonProject/滑块/极验4九宫格/pic/bg'
    # dir_path = r'/Users/jiangxia/PycharmProjects/pythonProject/滑块/极验4九宫格/pic/icon'
    files = os.listdir(dir_path)
    print(files)
    for file in files:
        img = os.path.join(dir_path, file)
        # print(img)
        with open(img, "rb") as rb:
            bg_img = rb.read()
        cropped_images = crop_image(bg_img, coordinates)
        # 一个个保存下来
        for j, img_crop in enumerate(cropped_images):
            img_crop.save(f"./image_test/bg/bg_{secrets.token_hex(4)}.jpg")

        # 图标格式转换
        # with open(img, "rb") as rb:
        #     icon_img = rb.read()
        # icon_img_jpg = convert_png_to_jpg(icon_img)
        # with open(f"./image_test/icon/icon_{secrets.token_hex(4)}.jpg", "wb") as wb:
        #     wb.write(icon_img_jpg)

    # with open("/Users/jiangxia/PycharmProjects/pythonProject/滑块/极验4九宫格/pic/bg/bg-1e898021.png", "rb") as rb:
    #     bg_img = rb.read()
    # cropped_images = crop_image(bg_img, coordinates)
    # # 一个个保存下来
    # for j, img_crop in enumerate(cropped_images):
    #     img_crop.save(f"./image_test/bg{j}.jpg")

    # # 图标格式转换
    # with open("image_test/icon_yizi.png", "rb") as rb:
    #     icon_img = rb.read()
    # icon_img_jpg = convert_png_to_jpg(icon_img)
    # with open("./image_test/icon_yizi.jpg", "wb") as wb:
    #     wb.write(icon_img_jpg)

然后自己根据小图的内容,命名分类。 一定要把小图也放进文件夹中,这样才可以保证准确率。

其中还要注意的是小图和极验 4 文字一样,需要渲染底图

其中文件夹内容长这样

然后运行他的 resnet18.py 进行训练。我这里是 80 轮,然后只留了最后一轮的,他的代码是每一轮训练的模型都会保存导致占用很大。

然后运行 pth2onnx.py 转为 onnx。接下来就可以整合代码了。

还需要注意的是

1
2
# 初始化模型 num_classes就是目录下的子文件夹数目,每个子文件夹对应一个分类,模型输出的向量长度也是这个长度
model = MyResNet18(num_classes=82)。

其中的 82 是你的文件夹个数,我这里只分类了 82 种,作者本人好像分类了 91 种。

最后就可以请求参数了。

1
'{"passtime":494,"userresponse":[[3,1],[2,1],[2,2]],"device_id":"","lot_number":"e4175cd409a14621b978acde8875adf0","pow_msg":"1|0|md5|2024-09-27T21:23:30.718157+08:00|54088bb07d2df3c46b79f80300b0abbe|e4175cd409a14621b978acde8875adf0||432a97d6c68575f0","pow_sign":"7b8ac143d55535860bf8bfab61bb4697","geetest":"captcha","lang":"zh","ep":"123","biht":"1426265548","gee_guard":{"roe":{"aup":"3","sep":"3","egp":"3","auh":"3","rew":"3","snh":"3","res":"3","cdc":"3"}},"A0Bw":"rO9P","em":{"ph":0,"cp":0,"ek":"11","wd":1,"nt":0,"si":0,"sc":0}}'

剩下就是参数了,极验 w 可以去 github 搜,开源挺多的,作者也是很贴心的,直接把坐标返回了[[],[],[]]的格式,我们直接替换 userresponse,其他的根据开源代码改改就能通过了。

结果

本文作者:skuukzky
本文链接:https://lpy30m.github.io/skuukzky.github.io/2024/09/27/%E9%AA%8C%E8%AF%81%E7%A0%81%E8%AF%86%E5%88%AB/%E6%9E%81%E9%AA%8C4%E4%B9%9D%E5%AE%AB%E6%A0%BC/
版权声明:本文采用 CC BY-NC-SA 3.0 CN 协议进行许可