您好,登录后才能下订单哦!
本篇文章为大家展示了怎么在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; } }
上述内容就是怎么在java中利用OpenCV破解顶象面积验证码,你们学到知识或技能了吗?如果还想学到更多技能或者丰富自己的知识储备,欢迎关注亿速云行业资讯频道。
免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。