如何提高滑块验证码的识别精度? - V2EX
V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
请不要在回答技术问题时复制粘贴 AI 生成的内容
aizya
V2EX    程序员

如何提高滑块验证码的识别精度?

  •  
  •   aizya 2024-07-24 14:47:50 +08:00 2153 次点击
    这是一个创建于 510 天前的主题,其中的信息可能已经有所发展或是发生改变。

    最近碰到一个需求,需要自动化操作一个网站,第一步就遇到一个问题,滑块验证码登录。

    核心逻辑是:

    1. 获取两张图片,一张左侧的验证码图片,一张完整的图片 2. 比对两张图片,获取到验证码图片与完整图片重合区域在 X 轴上需要移动的举例 3. 通过 selenium 缓慢移动验证码图片到重合区域,完成登录 

    在网上找到一个类似的需求和实现方案,跟着写了下代码 https://blog.csdn.net/weixin_53300120/article/details/138068169

    写了两个实现的方式:

    1. 采用 ddddocr:

       with open('left.png', 'rb') as f: target_bytes = f.read() with open('full.png', 'rb') as f: background_bytes = f.read() ocr = ddddocr.DdddOcr(det=False, ocr=False, show_ad=False) res = ocr.slide_match(target_bytes, background_bytes, simple_target=True) print(res, res['target'][0]) 
    2. 采用 cv2:

       # 加载图片 A 和 B image_a = cv2.imread('left.png', cv2.IMREAD_GRAYSCALE) image_b = cv2.imread('full.png', cv2.IMREAD_GRAYSCALE) # 使用模板匹配方法( Template Matching )寻找图片 A 在 B 中的位置 result = cv2.matchTemplate(image_b, image_a, cv2.TM_CCOEFF_NORMED) # 获取最大匹配值及其位置 min_val, max_val, min_loc, max_loc = cv2.minMaxLoc(result) # 如果 TM_CCOEFF_NORMED 方法使用,可以通过以下方式找到匹配位置的左上角坐标 top_left = max_loc # 获取图片 A 的宽度和高度 height, width = image_a.shape print(height, ':', width) height2, width2 = image_b.shape print(height2, ':', width2) # 获取最左侧的 x 坐标(左上角) leftmost_x = max_loc[0] print('leftmost_x:', leftmost_x) 

    现在的问题是,这两种方法的准确度都不高,而且我也不了解他们内部的实现方式,不知道如何提高识别的准确度。 现在用了一个比较笨的方法,死循环,重复 10 次以内大概率是可以成功一次。

    想请教大家,这种场景有没有啥好的办法可以提高识别的准确度,或者有没有相关的开源库可以直接用?

    感谢!

    15 条回复    2024-07-25 19:57:54 +08:00
    deepall
        1
    deepall  
       2024-07-24 15:07:40 +08:00
    不知道你的 left.png 和 full.png 是啥样,我用 ddddocr 和 cv2 识别验证码的准确率很高
    aizya
        2
    aizya  
    OP
       2024-07-24 15:14:41 +08:00
    @deepall 图片会动态变化,大概是这样的:

    full png:



    left png:

    deepall
        3
    deepall  
       2024-07-24 15:22:39 +08:00
    这个 ddddocr 感觉不太行,试试这个
    def generate_distance(slice_url, bg_url):
    """
    :param bg_url: 背景图地址
    :param slice_url: 滑块图地址
    :return: distance
    :rtype: Integer
    """
    slice_image = np.asarray(bytearray(requests.get(slice_url).content), dtype=np.uint8)
    slice_image = cv2.imdecode(slice_image, 1)
    slice_image = cv2.Canny(slice_image, 255, 255)

    bg_image = np.asarray(bytearray(requests.get(bg_url).content), dtype=np.uint8)
    bg_image = cv2.imdecode(bg_image, 1)
    bg_image = cv2.pyrMeanShiftFiltering(bg_image, 5, 50)
    bg_image = cv2.Canny(bg_image, 255, 255)

    result = cv2.matchTemplate(bg_image, slice_image, cv2.TM_CCOEFF_NORMED)

    min_val, max_val, min_loc, max_loc = cv2.minMaxLoc(result)

    return max_loc[0]
    aizya
        4
    aizya  
    OP
       2024-07-24 16:10:38 +08:00
    @deepall #3 一样的,也需要多次才能成功。
    naythefirst01
        5
    naythefirst01  
       2024-07-24 17:39:43 +08:00
    这样的直接模板匹配就可以了 准确率很低是不是图片获取的有问题 比如没有下载原始图或者没有处理缩放之类的
    uTOmOuk3L6sb4MSI
        6
    uTOmOuk3L6sb4MSI  
       2024-07-25 09:06:35 +08:00 via iPhone
    opencv 就行,成功率很高。我觉得文字识别和点选是更难的,不同大小、角度、颜色,甚至还有线条之类的干扰元素。我就会点滑块的,感觉不难。
    uTOmOuk3L6sb4MSI
        7
    uTOmOuk3L6sb4MSI  
       2024-07-25 09:09:46 +08:00 via iPhone
    我不明白为什么要很多次成功,cv2 这种模板匹配只有成功和不成功吧,执行再多次应该也是一种结果,不会出现一会失败一会成功的结果。
    brianinzz
        8
    brianinzz  
       2024-07-25 11:55:47 +08:00
    @ODD10 意思应该是给出的结果不对导致滑动了但是没通过
    uTOmOuk3L6sb4MSI
        9
    uTOmOuk3L6sb4MSI  
       2024-07-25 12:20:21 +08:00 via iPhone
    @brianinzz 不对可能就是得加减 x ,y 透明部份?一般没这么严格。说得不清不楚。看线框很吻合了,比手动都吻合。
    aizya
        10
    aizya  
    OP
       2024-07-25 14:39:37 +08:00
    @ODD10 #7 不不,执行多次是换张图片继续试,遇到简单的就过了。 不是一个图片跑多次。。
    uTOmOuk3L6sb4MSI
        11
    uTOmOuk3L6sb4MSI  
       2024-07-25 14:52:44 +08:00 via iPhone
    @aizya full 和 left 不是配对的吗?怎么只有一张图?而且 y 轴可能都不一样,缺口可能也不一样
    aizya
        12
    aizya  
    OP
       2024-07-25 16:43:32 +08:00
    @ODD10 #11 是两张图啊,你仔细看我 2 楼的回复
    uTOmOuk3L6sb4MSI
        13
    uTOmOuk3L6sb4MSI  
       2024-07-25 17:12:22 +08:00 via iPhone
    @aizya 反正我可以,而且我测试过几家滑块,成功率蛮高的
    aizya
        14
    aizya  
    OP
       2024-07-25 17:38:41 +08:00
    @ODD10 #13 方便提供一下你上面的代码吗?我运行看看问题出在什么地方?
    uTOmOuk3L6sb4MSI
        15
    uTOmOuk3L6sb4MSI  
       2024-07-25 19:57:54 +08:00
    没什么特别的,我用的 js

    ```js

    const cv = require('@u4/opencv4nodejs');

    // 加载图像
    const originalMat = cv.imread(__dirname + '/tmp/' + 'full.png');
    const templateMat = cv.imread(__dirname + '/tmp/' + 'left.png');

    //识别图片边缘
    bg_edge = originalMat.canny(100, 200);
    cut_edge = templateMat.canny(100, 200);

    // 转换图片格式
    bg_pic = bg_edge.cvtColor(cv.COLOR_GRAY2RGB);
    cut_pic = cut_edge.cvtColor(cv.COLOR_GRAY2RGB);

    // 进行模板匹配
    const matched = bg_pic.matchTemplate(cut_pic, cv.TM_CCOEFF_NORMED);

    // 归一化
    const minMax = matched.minMaxLoc();
    const {
    maxLoc: { x, y },
    } = minMax;

    console.log(JSON.stringify(minMax));

    // 绘制匹配区域的矩形框
    const point = new cv.Point(x, y);
    const color = new cv.Vec(255, 0, 0);
    const thickness = 2;
    originalMat.drawRectangle(
    new cv.Rect(point.x, point.y, templateMat.cols, templateMat.rows),
    color,
    thickness,
    cv.LINE_8
    );

    // 显示结果
    cv.imshow('Result', originalMat);
    cv.waitKey();

    ```
    关于     帮助文档     自助推广系统     博客     API     FAQ     Solana     4981 人在线   最高记录 6679       Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 29ms UTC 01:19 PVG 09:19 LAX 17:19 JFK 20:19
    Do have faith in what you're doing.
    ubao msn snddm index pchome yahoo rakuten mypaper meadowduck bidyahoo youbao zxmzxm asda bnvcg cvbfg dfscv mmhjk xxddc yybgb zznbn ccubao uaitu acv GXCV ET GDG YH FG BCVB FJFH CBRE CBC GDG ET54 WRWR RWER WREW WRWER RWER SDG EW SF DSFSF fbbs ubao fhd dfg ewr dg df ewwr ewwr et ruyut utut dfg fgd gdfgt etg dfgt dfgd ert4 gd fgg wr 235 wer3 we vsdf sdf gdf ert xcv sdf rwer hfd dfg cvb rwf afb dfh jgh bmn lgh rty gfds cxv xcv xcs vdas fdf fgd cv sdf tert sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf shasha9178 shasha9178 shasha9178 shasha9178 shasha9178 liflif2 liflif2 liflif2 liflif2 liflif2 liblib3 liblib3 liblib3 liblib3 liblib3 zhazha444 zhazha444 zhazha444 zhazha444 zhazha444 dende5 dende denden denden2 denden21 fenfen9 fenf619 fen619 fenfe9 fe619 sdf sdf sdf sdf sdf zhazh90 zhazh0 zhaa50 zha90 zh590 zho zhoz zhozh zhozho zhozho2 lislis lls95 lili95 lils5 liss9 sdf0ty987 sdft876 sdft9876 sdf09876 sd0t9876 sdf0ty98 sdf0976 sdf0ty986 sdf0ty96 sdf0t76 sdf0876 df0ty98 sf0t876 sd0ty76 sdy76 sdf76 sdf0t76 sdf0ty9 sdf0ty98 sdf0ty987 sdf0ty98 sdf6676 sdf876 sd876 sd876 sdf6 sdf6 sdf9876 sdf0t sdf06 sdf0ty9776 sdf0ty9776 sdf0ty76 sdf8876 sdf0t sd6 sdf06 s688876 sd688 sdf86