java opencv 计算滑块横移距离

3 篇文章 0 订阅

目标

滑块验证是现在用的较为普遍的验证是否为机器人的方案,也相对其他验证来说比较好破解的,因为只需要计算出滑块横移距离就行

思路

想要计算距离得知道如下几个数据,假设图片左下角为坐标原点O

  • 滑块在图中的的起始坐标(图中B点x坐标)
  • 缺口在原图中的坐标(图中A点坐标)

在这里插入图片描述
第一问题好解决下html代码就知道了

主要是第二个问题
得通过某种方式得到原图中缺口的位置,再根据比例缩小坐标值就行

解决过程

滑块在图中的的起始坐标

<img class="tc-jpp-img unselectable" 
     alt="" id="slideBlock" 
     src="https://hy.captcha.qq.com/(图片url)" 
     style="height: 68px; width: 68px; top: 60px; left: 26px;">

现在知道滑块左上角B点的x坐标了

缺口在原图中的坐标

原图地址在html中同样可以拿到

网上的破解原理应该已经很多,我这里说一种方案就是利用opencv的模糊匹配api找到指定的图片在原图中最准确的坐标

现在两张图片如下

一张是滑块背景图
在这里插入图片描述
在这里插入图片描述
一张是滑块图
我们可以通过程序将背景图片进行处理,让那个缺口变得非常显眼,比如说将图片变成
在这里插入图片描述
同理将滑块也进行处理,变成如下这样
在这里插入图片描述
opencv是一个好东西,大家网上查查资料就知道java怎么玩

处理背景图

  1. 将图片高斯模糊
  2. 灰度化处理
  3. 二值化处理
高斯模糊处理
// 读取背景原图
Mat src = Imgcodecs.imread("图片路径", Imgcodecs.IMREAD_UNCHANGED);
// 存储处理后的图片数据
Mat dst = new Mat();
// 高斯模糊处理
Imgproc.GaussianBlur(src, dst, new Size(9,9), 0, 0, Core.BORDER_DEFAULT);

// 存储在本地
Imgcodecs.imwrite("修改后的图片路径", dst);

在这里插入图片描述
这就是高斯模糊之后的效果

灰度化处理
// 部分代码省略
Imgproc.cvtColor(src, dst, Imgproc.COLOR_BGR2GRAY);

在这里插入图片描述
处理之后效果

二值化
Imgproc.threshold(dst, dst, 0, 255, Imgproc.THRESH_BINARY | Imgproc.THRESH_OTSU);

在这里插入图片描述
到这里背景图处理完成

处理滑块图

  1. 灰度化处理
  2. 二值化处理
  3. 黑白像素反转

前两部代码和上面一样,处理之后结果
在这里插入图片描述

反转像素
	Mat clone = src.clone();
	int rows = clone.rows();
	int cols = clone.cols();
	for (int i = 0; i < rows; i++) {
	    for (int j = 0; j < cols; j++) {
	        double[] doubles = clone.get(i, j);
	
	        doubles[0] = 255 - doubles[0];
	        if (doubles.length > 1){
	            doubles[1] = 255 - doubles[1];
	        }
	        clone.put(i, j, doubles);
	    }
	}
   return clone;

处理之后就是最终效果

计算滑块位置

     // 背景图
	 Mat clone = source.clone();
	// 处理结果
     Mat result = new Mat();
     // 匹配结果
     Imgproc.matchTemplate(source, target, result, Imgproc.TM_CCORR_NORMED);
     Core.normalize(result, result, 0, 1, Core.NORM_MINMAX, -1, new Mat());
     // 获取匹配结果坐标
     Core.MinMaxLocResult minMaxLocResult = Core.minMaxLoc(result);
     org.opencv.core.Point maxLoc = minMaxLocResult.maxLoc;
	 // 在图上做标记
     Imgproc.rectangle(clone, maxLoc,
				     new Point(maxLoc.x + target.cols(),maxLoc.y + target.rows()),
				     new Scalar(0, 255, 0));

     Imgcodecs.imwrite(SlideUtils.BASE_PATH + File.separator + "match.jpg", clone);
     return maxLoc;

在这里插入图片描述
图片中的多余空格是因为滑块图就是有白色的间隔,这个影响因素可以通过后期修改

现在可以拿到大致的坐标了,但是此时的坐标也只是原图中的坐标,还不是实际页面背景图中的坐标,需要按比例缩小,那如何缩小呢
滑块如果要吻合的话,那么 原图滑块大小/页面滑块的大小 = 原图背景大小/页面背景大小
不是绝对,是近似,大家可以通过页面数据验证
在这里插入图片描述
在这里插入图片描述
680/341=1.99
136/68=1.99
那么原图中滑块缺口的x坐标/刚才比例就是页面实际缺口A的x坐标,再和上文中的滑块B点的x坐标相减就可以了,当然这个结果是有误差的,就是因为滑块的背景有白色边框干扰,这个数字通过多次尝试是可以大致计算出来的

总结

方法还是很多的,还可以通过边框模糊匹配,准确率更高
其实这些方法都是网上人家大牛玩剩下的,但是基本上都是python代码,作为java程序员还是想手动实现下
搞这个就是为了好玩,没别的意思

参考

https://segmentfault.com/a/1190000019218588

评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值