滑块验证码破解----Java使用opencv后端破解滑块验证

使用技术:Java  + SpringBoot+openCV

在windows上首先需要下载opencv进行安装,先去官网:Releases - OpenCV 下载这个windows版本的安装包

下载后直接安装解压就行,然后需要,然后找到安装位置里的这个文件: 

你下载的是什么版本的,这里的数字就是多少,比如我下载4.5.3版本那么这里就是453,下载4.9.0这里就显示490

 这个文件是外部库,在使用opencv的时候需要用到这个文件

代码:

图片工具类:

import cn.hutool.core.io.IoUtil;
import org.opencv.core.Core;
import org.opencv.core.Mat;
import org.opencv.core.Point;
import org.opencv.imgcodecs.Imgcodecs;
import org.opencv.imgproc.Imgproc;
import org.springframework.stereotype.Component;

import javax.imageio.ImageIO;
import java.awt.image.BufferedImage;
import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.OutputStream;
import java.util.Base64;
import java.util.UUID;


/**
 * 图片工具
 *
 * @author Jerry
 * @date 2024/04/17
 */
@Component
public class PictureUtil {
    /**
     * opencv库的dll路径    todo 需要改成自己的
     */
    public static final String dllPath = "J:/opencv/opencv/build/java/x64/opencv_java453.dll";

    /**
     * 保存临时文件的路径
     */
    public static final String savePath = "D:/pngtemp";
    /**
     * png文件后缀
     */
    public static final String pngFileSuffix = ".png";

    static {
        //加载
        System.load(dllPath);

    }


    /**
     * 通过opencv库获取验证码需要移动的距离  获取横坐标
     *
     * @param bUrlBase64 b 大图片的base64
     * @param sUrlBase64 s 小图片的base64
     * @return double
     */
    public static double getDistanceByBase64ByOpenCv(String bUrlBase64, String sUrlBase64) {
        // 读取背景图
        String bFilePath = base64ToPNG(bUrlBase64);
        Mat background = Imgcodecs.imread(bFilePath);
        // 读取滑块图
        String sFilePath = base64ToPNG(sUrlBase64);
        Mat slider = Imgcodecs.imread(sFilePath);

        // 使用模板匹配来找到滑块在背景图中的位置
        Mat result = new Mat();
        Imgproc.matchTemplate(background, slider, result, Imgproc.TM_CCOEFF_NORMED);

        Core.MinMaxLocResult mmr = Core.minMaxLoc(result);
        Point matchLoc = mmr.maxLoc;
        //删除临时文件
        deleteFile(bFilePath, sFilePath);
        return matchLoc.x;
    }

    /**
     * 删除文件
     *
     * @param bFilePath b文件路径
     */
    public static void deleteFile(String... bFilePath) {
        for (String path : bFilePath) {
            try {
                new File(path).delete();
            } catch (Exception ignored) {
            }
        }

    }

    /**
     * 将base64转为图片
     *
     * @param base64String base64字符串
     */
    public static String base64ToPNG(String base64String) {
        //文件名
        String outputFileName = savePath + "/" + UUID.randomUUID().toString() + pngFileSuffix;
        ByteArrayInputStream bis = null;
        OutputStream os = null;
        try {
            // 解码base64数据
            byte[] decodedBytes = Base64.getDecoder().decode(base64String);

            // 将解码后的数据转换为图像
            bis = new ByteArrayInputStream(decodedBytes);
            BufferedImage image = ImageIO.read(bis);

            // 将图像保存为PNG文件
            os = new FileOutputStream(outputFileName);
            ImageIO.write(image, "png", os);

            bis.close();
            os.close();
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            //关闭流
            IoUtil.close(bis);
            IoUtil.close(os);
        }
        return outputFileName;
    }

    /**
     * 只删开头
     *
     * @param str str
     * @return {@link String}
     */
    public static String substringBase64OnlyBegin(String str) {
        return str.substring(str.indexOf(",") + 1);
    }


    public static int findSliderPosition(String bUrlBase64, String sUrlBase64) {
        BufferedImage background = base64ToBufferedImage(bUrlBase64);
        BufferedImage slider = base64ToBufferedImage(sUrlBase64);
        ;


        double minDiff = Double.MAX_VALUE;
        int sliderXCoordinate = 0;

        for (int x = 0; x < background.getWidth() - slider.getWidth(); x++) {
            double diff = 0;
            for (int i = 0; i < slider.getWidth(); i++) {
                for (int j = 0; j < slider.getHeight(); j++) {
                    int rgb1 = background.getRGB(x + i, j);
                    int rgb2 = slider.getRGB(i, j);
                    int r1 = (rgb1 >> 16) & 0xFF;
                    int g1 = (rgb1 >> 8) & 0xFF;
                    int b1 = (rgb1 & 0xFF);
                    int r2 = (rgb2 >> 16) & 0xFF;
                    int g2 = (rgb2 >> 8) & 0xFF;
                    int b2 = (rgb2 & 0xFF);
                    diff += Math.pow(r1 - r2, 2) + Math.pow(g1 - g2, 2) + Math.pow(b1 - b2, 2);
                }
            }
            diff /= (slider.getWidth() * slider.getHeight());
            if (diff < minDiff) {
                minDiff = diff;
                sliderXCoordinate = x;
            }
        }
        return sliderXCoordinate;
    }

    /**
     * base64到缓冲图像
     *
     * @param base64str base64str
     * @return {@link BufferedImage}
     */
    private static BufferedImage base64ToBufferedImage(String base64str) {
        try {
            byte[] imageBytes = Base64.getDecoder().decode(base64str);
            ByteArrayInputStream bis = new ByteArrayInputStream(imageBytes);
            // 读取为BufferedImage
            return ImageIO.read(bis);
        } catch (Exception e) {
            System.out.println("转换失败");
        }
        return null;

    }
}
测试方法:
    /**
     * 测试方法
     * @param args
     */
    public static void main(String[] args) {
        //大图片的base64
        String bigbase64 = null;
        //小图片的base64
        String smallbase64 = null;
        //返回得到的是X轴的距离(我的项目只需要X轴距离)   但是实际上在getDistanceByBase64ByOpenCv这个方法中,已经得到了X轴和Y轴的距离
        double XDistance = PictureUtil.getDistanceByBase64ByOpenCv(bigbase64, smallbase64);
    }

 pom依赖:
        <dependency>
            <groupId>org.openpnp</groupId>
            <artifactId>opencv</artifactId>
            <version>4.5.3</version>
        </dependency>

 这里的pom依赖需要根据你下载的opencv版本进行调整

这个滑块识别的方法比网上的方法好用多了,识别正确率很高,3次之内必正确

如果提示缺jar包,那就需要去这里找对应的jar包引入到项目中:

具体引入方法:

按顺序操作即可引入.

如果还有任何不懂,可在评论区或者私信问我,欢迎各位一起探讨

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/581789.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

分治策略 --- 快排归并

目录 分治-快排 一、颜色分类 二、排序数组 三、数组中的第K个最大元素 四、库存管理 分治-归并 一、排序数组 二、交易逆序对的总数 三、计算右侧小于当前元素的个数 四、翻转对 分治是一种思想&#xff0c;也就是将大问题分解成小问题&#xff0c;一直分到小问题可…

2024年云仓酒庄新动态合肥北京双城开课,持续培训助力酒业发展

云仓酒庄合肥北京双城开课&#xff0c;持续培训助力酒业发展 随着国内酒类市场的不断繁荣与消费需求的日益增长&#xff0c;云仓酒庄作为行业内的稳扎稳打之一的企业&#xff0c;始终致力于提升服务质量和品牌影响力。近日&#xff0c;云仓酒庄在合肥与北京两地同时开设培训课…

qt学习篇---C++基础学习

本学习笔记学习下面视频总结&#xff0c;感兴趣可以去学习。讲的很详细 【北京迅为】嵌入式学习之QT学习篇_哔哩哔哩_bilibilihttps://www.bilibili.com/video/BV1tp4y1i7EJ/?spm_id_from333.337.search-card.all.click&vd_source8827cc0da16223b9f2ad8ae7111de9e2 目录 C…

JavaScript数组方法练习

第一个练习 ● 计算所有账户的存款总额 const bankDepositSum accounts //定义一个变量.flatMap(acc > acc.movements) //使用flatmap将所有的存款提取&#xff0c;然后组成一个新的数组.filter(mov > mov > 0) //使用filter方法提取所有的正值.reduce((sum, c…

【前端】VUE项目创建

在所需文件夹中打开cmd命令行窗口&#xff0c;输入vue ui 进入web可视化界面选择创建新项目 根据需求依次完成下列选择&#xff0c;下列是参考配置&#xff0c;完成后点击创建项目即可 最终显示完成

upload-labs后续(14-)

图片马 在图片中加入木马&#xff0c;然后上传让浏览器解析&#xff0c;达到上传木马的目的 制作图片马&#xff1a;可以在notepad或者winhex中打开文件&#xff0c;在文件头中加入图片的文件头&#xff0c;再在文件末尾加入木马即可。 图片文件头如下&#xff1a; 1.Png图片…

B站广告推广开户最低需要多少钱?

在竞争激烈的互联网营销环境中&#xff0c;哔哩哔哩&#xff08;B站&#xff09;作为深受年轻人喜爱的视频分享平台&#xff0c;其广告价值不容小觑。对于希望在B站上进行广告推广的企业或个人而言&#xff0c;了解开户流程及成本&#xff0c;选择专业的服务团队至关重要。介绍…

AI图书推荐:ChatGPT写论文的流程与策略

论文一直是任何学术学位的顶峰。它展示了学生在研究领域的兴趣和专业知识。撰写论文也是一个学习经验&#xff0c;为学术工作以及专业研究角色做好准备。但是&#xff0c;论文工作总是艰苦的&#xff0c;通常是充满乐趣和创造性的&#xff0c;但有时也是乏味和无聊的。生成式人…

kerberos-hive-dbeaver问题总结

一、kerberos安装windows客户端 1、官方下载地址 http://web.mit.edu/kerberos/dist/ 2、环境变量配置 下载msi安装包&#xff0c;无需重启计算机&#xff0c;调整环境变量在jdk的前面&#xff0c;尽量靠前&#xff0c;因为jdk也带了kinit、klist等命令 C:\Program Files\…

Kotlin泛型之 循环引用泛型(A的泛型是B的子类,B的泛型是A的子类)

IDE(编辑器)报错 循环引用泛型是我起的名字&#xff0c;不知道官方的名字是什么。这个问题是我在定义Android 的MVP时提出来的。具体是什么样的呢&#xff1f;我们看一下我的基础的MVP定义&#xff1a; interface IPresenter<V> { fun getView(): V }interface IVie…

41. UE5 RPG 设置火球术的碰撞类型

在上一篇中&#xff0c;我们设置了火球术从发射到击中敌人的整个周期使用的音效和特效&#xff0c;现在看上去它像一个真正的火球术了。在这一篇文章里面&#xff0c;我们主要解决一下火球术碰撞的问题&#xff0c;现在已知的问题是&#xff0c;有些不需要和火球产生碰撞的物体…

代码随想录-二叉树(节点)

目录 104. 二叉树的最大深度 题目描述&#xff1a; 输入输出描述&#xff1a; 思路和想法&#xff1a; 111. 二叉树的最小深度 题目描述&#xff1a; 输入输出描述&#xff1a; 思路和想法&#xff1a; 222. 完全二叉树的节点个数 题目描述&#xff1a; ​输入输出描…

商汤研究院招大模型实习生

商汤研究院招大模型实习生&#xff0c;base上海、北京&#xff0c;400/day。福利&#xff1a;每天50租房补贴&#xff0c;20的餐补。晚上8点之后回去有额外的25元晚餐餐补&#xff0c;10点之后回去可以免费用滴滴。 组内的大模型工作大概分两个方向&#xff1a; 1.3B、3B等小…

特别的时钟特别的倒计时

念念不忘的歌曲&#xff1a;Thats Why You Go Away <!DOCTYPE html> <html lang"zh-CN"> <head><meta charset"UTF-8"><meta name"viewport" content"widthdevice-width, initial-scale1.0"><title&…

IDEA新版本创建Spring项目只能勾选17和21却无法使用Java8的完美解决方案

想创建一个springboot的项目&#xff0c;使用Spring Initializr创建项目时&#xff0c;发现版本只有17&#xff5e;21&#xff0c;无法选择Java8。 我们知道IDEA页面创建Spring项目&#xff0c;其实是访问spring initializr去创建项目。我们可以通过阿里云国服间接创建Spring项…

工业异常检测

工业异常检测在业界和学界都一直是热门&#xff0c;近期其更是迎来了全新突破&#xff1a;与大模型相结合&#xff01;让异常检测变得更快更准更简单&#xff01; 比如模型AnomalyGPT&#xff0c;它克服了以往的局限&#xff0c;能够让大模型充分理解工业场景图像&#xff0c;判…

Redis哈希槽和一致性哈希

前言 单点的Redis有一定的局限&#xff1a; 单点发生故障&#xff0c;数据丢失&#xff0c;影响整体服务应用自身资源有限&#xff0c;无法承载更多资源分配并发访问&#xff0c;给服务器主机带来压力&#xff0c;性能瓶颈 我们想提升系统的容量、性能和可靠性&#xff0c;就…

paddleocr C++生成dll

目录 编译完成后修改内容: 新建ppocr.h头文件 注释掉main.cpp内全部内容&#xff0c;将下面内容替换进去。ppocr.h需要再环境配置中包含进去头文件 然后更改配置信息&#xff0c;将exe换成dll 随后右击重新编译会在根目录生成dll,lib文件。 注意这些dll一个也不能少。生成…

伪装目标检测论文阅读 SAM大模型之参数微调:Conv LoRA

paper&#xff1a;link code&#xff1a;还没公开 摘要 任意分割模型(SAM)是图像分割的基本框架。虽然它在典型场景中表现出显著的零镜头泛化&#xff0c;但当应用于医学图像和遥感等专门领域时&#xff0c;其优势就会减弱。针对这一局限性&#xff0c;本文提出了一种简单有效…

Java进阶-JavaStreamAPI的使用

本文全面介绍了 Java Stream API 的概念、功能以及如何在 Java 中有效地使用它进行集合和数据流的处理。通过详细解释和示例&#xff0c;文章展示了 Java Stream API 在简化代码、提高效率以及支持函数式编程方面的优势。文中还比较了 Java Stream API 与其他集合处理库的异同&…