滑块验证码破解----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包引入到项目中:

具体引入方法:

按顺序操作即可引入.

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

  • 7
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
好的,关于人脸识别的问题,以下是使用OpenCV-Java实现人脸识别的代码示例: 1. 引入OpenCV-Java库 在项目中引入OpenCV-Java库,可以从官网下载对应的版本,引入后,我们就可以调用OpenCV-Java提供的API来实现人脸识别。 2. 加载人脸识别器 在使用OpenCV-Java实现人脸识别前,我们需要加载一个训练好的分类器,可以使用官方提供的人脸识别模型,或自己训练。加载过程如下: ``` CascadeClassifier faceDetector = new CascadeClassifier("haarcascade_frontalface_alt.xml"); ``` 3. 读取图片并识别人脸 加载分类器后,我们可以读取一张图片并进行人脸识别,具体实现代码如下: ``` Mat image = Imgcodecs.imread("test.jpg"); // 读取图片 Imgproc.cvtColor(image, image, Imgproc.COLOR_BGR2GRAY); // 转为灰度图 Imgproc.equalizeHist(image, image); // 直方图均衡化,提高图像质量 Rect[] faces = faceDetector.detectMultiScale(image); // 识别人脸 for (Rect rect : faces) { Imgproc.rectangle(image, new Point(rect.x, rect.y), new Point(rect.x + rect.width, rect.y + rect.height), new Scalar(0, 255, 0)); // 绘制人脸框 } Imgcodecs.imwrite("result.jpg", image); // 保存结果 ``` 其中,`detectMultiScale` 方法用于检测出图像中的人脸,返回一个`Rect`类型的数组,每个元素代表一个人脸的位置和大小。 4. 运行程序 将以上代码放入一个Java类中,运行程序即可实现人脸识别。注意,需要引入`org.opencv.core.Mat`、`org.opencv.core.Rect`、`org.opencv.core.Point`、`org.opencv.core.Scalar`、`org.opencv.imgcodecs.Imgcodecs`、`org.opencv.imgproc.Imgproc`等OpenCV-Java的类。 希望能够对您有所帮助!

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值