使用java + OpenCV破解顶象面积验证码的示例

前言

我们又来破解验证码啦,今天上场的是–顶象面积验证码

根据场景来看,我们需要根据图片中分隔好的区域找到面积最大的一块来点击它。

那么我们把它拆分成以下几个步骤:

检测出图中标记的点将检测出来的点连成线根据线分割出的区域计算各区域面积,并得到最大面积在该区域面积中选取一个坐标点作为结果

一、检测出图中标记的点

第一个问题,怎么检测出图片中被标记出来的点?

这里使用哈里斯角点检测,这里采用OpenCV中的cornerHarris()来实现。
参考下面两篇文章,感兴趣的话可以阅读一下:

Harris角点检测原理详解图像特征之Harris角点检测

效果如下图

/**
	 * 哈里斯角点检测
	 * @param img	原图地址
	 * @param img2	新图地址
	 */
	public void getHarris(String img,String img2) {
		System.load(dllPath);
		File bFile = new File(img);
		try {
			Mat mat = Imgcodecs.imread(bFile.getPath());
			// 转灰度图像
			Mat gray = new Mat();
			Imgproc.cvtColor(mat, gray, Imgproc.COLOR_BGR2GRAY);
			// 角点发现
			Mat harris = new Mat();
			Imgproc.cornerHarris(gray, harris, 2, 3, 0.04);
			// 绘制角点
			float[] floats = new float[harris.cols()];
			for (int i = 0; i < harris.rows(); i++) {
				harris.get(i, 0, floats);
				for (int j = 0; j < floats.length; j++) {
					if (floats[j] > 0.0001) {// 越接近于角点数值越大
						System.out.println(floats[j]);
						Imgproc.circle(mat, new Point(j, i), 1, new Scalar(0, 255, 0));
					}
				}
			}
			Imgcodecs.imwrite(img2, mat);
		} catch (Throwable e) {
			e.printStackTrace();
		}
	}

那标记点的检测完成了。

二、将检测出来的点连成线

如何连线就比较简单了,这里我们只需要在绘制角点的时候将浸染范围设置大一点就好了,这里设置为5即可。

Imgproc.circle(mat, new Point(j, i), 5, new Scalar(0, 255, 0));

下面是效果图

连线做到这样的效果就可以了。

三、根据线分割出的区域计算各区域面积,并得到最大面积

这里根据深度优先搜索的原理,划分不同区域最终选出最大的一块面积;

深度优先搜索大家不会的话就可以参考这篇文章:
基本算法——深度优先搜索(DFS)和广度优先搜索(BFS)

这里直接搜索了所有区域。将占像素量最多的区域显示了出来,效果如图:

/**根据线分割出的区域计算各区域面积,并得到最大面积
	 * @param oldimg 原图
	 * @param newimg 绘制角点后的图
	 */
	 */
	public void getMatrix(String oldimg,String newimg) {
		File ofile = new File(oldimg);
		File nfile = new File(newimg);
		try {
			BufferedImage oimage = ImageIO.read(ofile);
			BufferedImage nimage = ImageIO.read(nfile);
			int matrix[][] = new int[nimage.getWidth()][nimage.getHeight()];
			int rank = 0;
			int maxRank = 0;
			int count = 0;
			int maxCount = 0;
			//将检测并高亮部分置1,其余部分置0,得到一个代替图的二维数组
			for (int w = 0; w < nimage.getWidth(); w++) {
				for (int h = 0; h < nimage.getHeight(); h++) {
					int[] bgRgb = new int[3];
					bgRgb[0] = (nimage.getRGB(w, h) & 0xff0000) >> 16;
					bgRgb[1] = (nimage.getRGB(w, h) & 0xff00) >> 8;
					bgRgb[2] = (nimage.getRGB(w, h) & 0xff);
					if (!(bgRgb[0] <= 70 && bgRgb[1] >= 180 && bgRgb[2] <= 70)) {
						matrix[w][h] = 0;
					} else {
						matrix[w][h] = -1;
					}
				}
			}
			//深度优先搜索找出最大区域
			while (true) {
				int n = 0;
				for (int i = 0; i < matrix.length; i++) {
					for (int j = 0; j < matrix[0].length; j++) {
						if (matrix[i][j] == 0) {
							n++;
							rank++;
							count = dfs(matrix, rank);
							if (count > maxCount) {
								maxCount = count;
								maxRank = rank;
							}
						}
					}
				}
				if (n == 0)
					break;
			}
			//改变最大区域颜色
			for (int j = 0; j < matrix[0].length; j++) {
				for (int i = 0; i < matrix.length; i++) {
					if (matrix[i][j] == maxRank){
						nimage.setRGB(i, j, new Color(0, 0, 255).getRGB());
					}
				}
			}
			ImageIO.write(image, "png", new File(img));
		} catch (IOException e) {
			e.printStackTrace();
		}
	}
	/**
	 * 深度优先搜索
	 * @param matrix 图信息数组
	 * @param n 标记数
	 * @return
	 */
	public int dfs(int matrix[][], int rank) {
		int count = 0;
		int w = -1;
		int h = -1;
		for (int i = 0; i < matrix.length; i++) {
			for (int j = 0; j < matrix[0].length; j++) {
				if (matrix[i][j] == 0) {
					w = i;
					h = j;
					break;
				}
			}
			if (w != -1) {
				break;
			}
		}
		Stack<JSONObject> stack = new Stack<JSONObject>();
		while (matrix[w][h] == 0 || h == stack.peek().getIntValue("h") && w == stack.peek().getIntValue("w")) {
			JSONObject json = new JSONObject();
			json.put("w", w);
			json.put("h", h);
			stack.push(json);
			matrix[w][h] = rank;
			count++;
			if (h + 1 < matrix[0].length) {
				if (matrix[w][h + 1] == 0) {
					h = h + 1;
					continue;
				}
			}
			if (w + 1 < matrix.length) {
				if (matrix[w + 1][h] == 0) {
					w = w + 1;
					continue;
				}
			}
			if (h - 1 >= 0) {
				if (matrix[w][h - 1] == 0) {
					h = h - 1;
					continue;
				}
			}
			if (w - 1 >= 0) {
				if (matrix[w - 1][h] == 0) {
					w = w - 1;
					continue;
				}
			}
			stack.pop();
			if (!stack.empty()) {
				if (h == stack.peek().getIntValue("h") && w == stack.peek().getIntValue("w")) {
					stack.pop();
				}
			}
			if (!stack.empty()) {
				w = stack.peek().getIntValue("w");
				h = stack.peek().getIntValue("h");
			} else {
				break;
			}
		}
		return count;
	}

四、 在该区域面积中选取一个坐标点作为结果

这里我们都已经找到面积最大区域了,就随意取一个点就好了

将上面代码中的

//改变最大区域颜色
for (int j = 0; j < matrix[0].length; j++) {
	for (int i = 0; i < matrix.length; i++) {
		if (matrix[i][j] == maxRank){
			nimage.setRGB(i, j, new Color(0, 0, 255).getRGB());
		}
	}
}

改为下面的代码即可

//标记选取到的点
boolean flag = false;
for (int j = 0; j < matrix[0].length; j++) {
	for (int i = 0; i < matrix.length; i++) {
		if (matrix[i][j] == maxRank) {
			oimage.setRGB(i, j, new Color(255, 0, 0).getRGB());
			System.out.println("w=" + i + "|h=" + j);
			flag = true;
			break;
		}
	}
	if (flag) {
		break;
	}
}

结果展示:

本文思路参考:https://blog.csdn.net/aaronjny/article/details/110245896

到此这篇关于使用java + OpenCV破解顶象面积验证码的示例的文章就介绍到这了,更多相关java顶象面积验证码内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

(0)

相关推荐

  • 使用java + selenium + OpenCV破解腾讯防水墙滑动验证码功能

    * 验证码地址:https://007.qq.com/online.html * 使用OpenCv模板匹配 * 成功率90%左右 * Java + Selenium + OpenCV 产品样例 来吧!展示! 注意!!! · 在模拟滑动时不能按照相同速度或者过快的速度滑动,需要向人滑动时一样先快后慢,这样才不容易被识别. 模拟滑动代码↓↓↓ /** * 模拟人工移动 * @param driver * @param element页面滑块 * @param distance需要移动距离 */ pu

  • JavaWeb简单用户登录注册实例代码(有验证码)

    需求 编写login登录界面(用户名,密码,验证码,登陆按钮,注册按钮) 设计关系数据库(编号,用户名,密码) 编写注册功能,将数据存储在数据库中.(姓名不能重复,设为主键,重复会注册失败) 编写登录功能 .首先获取验证码,先判断验证码是否正确,不正确则显示验证码错误.验证码正确后再获取用户名和密码,进行数据库的搜索比对,若正确则重定向到成功的界面,并且将用户名显示. jar包 技术选型 Servlet + JSP + Mysql + JDBCTemplate + Druid + BeanUti

  • 使用java + selenium + OpenCV破解网易易盾滑动验证码的示例

    网易易盾:dun.163.com * 验证码地址:https://dun.163.com/trial/jigsaw * 使用OpenCv模板匹配 * Java + Selenium + OpenCV 产品样例 接下来就是见证奇迹的时刻! 注意!!! · 在模拟滑动时不能按照相同速度或者过快的速度滑动,需要向人滑动时一样先快后慢,这样才不容易被识别. 模拟滑动代码↓↓↓ /** * 模拟人工移动 * @param driver * @param element页面滑块 * @param dista

  • Java 生成图片验证码3种方法(字母、加减乘除、中文)

    第一种方法 全是字母和数字组成 package com.myFirstSpring.util; import java.awt.Color; import java.awt.Font; import java.awt.Graphics; import java.awt.image.BufferedImage; import java.io.IOException; import java.util.Random; import javax.imageio.ImageIO; import java

  • 使用java + OpenCV破解顶象面积验证码的示例

    前言 我们又来破解验证码啦,今天上场的是–顶象面积验证码 根据场景来看,我们需要根据图片中分隔好的区域找到面积最大的一块来点击它. 那么我们把它拆分成以下几个步骤: 检测出图中标记的点将检测出来的点连成线根据线分割出的区域计算各区域面积,并得到最大面积在该区域面积中选取一个坐标点作为结果 一.检测出图中标记的点 第一个问题,怎么检测出图片中被标记出来的点? 这里使用哈里斯角点检测,这里采用OpenCV中的cornerHarris()来实现. 参考下面两篇文章,感兴趣的话可以阅读一下: Harri

  • selenium+java破解极验滑动验证码的示例代码

    摘要 分析验证码素材图片混淆原理,并采用selenium模拟人拖动滑块过程,进而破解验证码. 人工验证的过程 1.打开威锋网注册页面 2.移动鼠标至小滑块,一张完整的图片会出现(如下图1) 3.点击鼠标左键,图片中间会出现一个缺块(如下图2) 4.移动小滑块正上方图案至缺块处 5.验证通过 selenium模拟验证的过程 加载威锋网注册页面 下载图片1和缺块图片2 根据两张图片的差异计算平移的距离x 模拟鼠标点击事件,点击小滑块向右移动x 验证通过 详细分析 1.打开chrome浏览器控制台,会

  • Java实现滑动验证码的示例代码

    最近滑动验证码在很多网站逐步流行起来,一方面对用户体验来说,比较新颖,操作简单,另一方面相对图形验证码来说,安全性并没有很大的降低.当然到目前为止,没有绝对的安全验证,只是不断增加攻击者的绕过成本. 接下来分析下滑动验证码的核心流程: 后端随机生成抠图和带有抠图阴影的背景图片,后台保存随机抠图位置坐标 前端实现滑动交互,将抠图拼在抠图阴影之上,获取到用户滑动距离值,比如以下示例 前端将用户滑动距离值传入后端,后端校验误差是否在容许范围内. 这里单纯校验用户滑动距离是最基本的校验,出于更高的安全考

  • Java随机生成手机短信验证码的方法

    本文实例讲述了Java随机生成手机短信验证码的方法.分享给大家供大家参考,具体如下: /** * 创建指定数量的随机字符串 * @param numberFlag 是否是数字 * @param length * @return */ public static String createRandom(boolean numberFlag, int length){ String retStr = ""; String strTable = numberFlag ? "1234

  • Java中SSM+Shiro系统登录验证码的实现方法

     先给大家展示下效果图: 1.验证码生成类: import java.util.Random; import java.awt.image.BufferedImage; import java.awt.Graphics; import java.awt.Font; import java.awt.Color; /** * 验证码生成器类,可生成数字.大写.小写字母及三者混合类型的验证码. 支持自定义验证码字符数量: 支持自定义验证码图片的大小: 支持自定义需排除的特殊字符: * 支持自定义干扰线

  • Java+OpenCV实现人脸检测并自动拍照

    java+opencv实现人脸检测,调用笔记本摄像头实时抓拍,人脸会用红色边框标识出来,并且将抓拍的目录存放在src下,图片名称是时间戳. 环境配置:win7 64位,jdk1.8 CameraBasic.java package com.njupt.zhb.test; import java.awt.EventQueue; import javax.swing.ImageIcon; import javax.swing.JFrame; import javax.swing.JLabel; im

  • Java OpenCV实现图像镜像翻转效果

    本文实例为大家分享了Java OpenCV实现图像镜像翻转效果的具体代码,供大家参考,具体内容如下 主要使用OpenCV的flip()方法,可以实现图像的垂直.水平以及同时垂直镜像翻转. flip是Core的静态方法,用法为: public static void flip(Mat src, Mat dst, int flipCode) 参数说明: src:输入图像: dst:输出图像: flipCode: = 0 图像向下翻转 > 0 图像向右翻转 < 0 图像同时向下向右翻转 代码如下:

  • 基于Java随机生成手机短信验证码的实例代码

    简单版 /** * 产生4位随机数(0000-9999) * * @return 4位随机数 */ public static String getFourRandom() { return StringUtils.leftPad(new Random().nextInt(10000) + "", 4, "0"); } 复杂版 /** * 创建指定数量的随机字符串 * @param numberFlag 是否是数字 * @param length * @return

随机推荐