Use java + OpenCV to crack the top image area verification code

Preface
Insert picture description here

Let’s crack the verification code again. Today is the verification code for the top image area
Insert picture description here

According to the scene, we need to find the largest area according to the separated area in the picture and click on it.

Then we split it into the following steps:

  1. Detect the marked points in the figure
  2. Connect the detected points into a line
  3. Calculate the area of ​​each area according to the area divided by the line, and get the largest area
  4. Select a coordinate point in the area of ​​the area as the result

1. Detect the points marked in the figure

The first question, how to detect the marked points in the picture?

As used herein, the Harris corner point detection , where the use of OpenCV cornerHarris () is achieved.
Refer to the following two articles, if you are interested, you can read it:

The effect is as follows
Insert picture description here

	/**
	 * 哈里斯角点检测
	 * @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();
		}
	}

The detection of the marking point is complete.

2. Connect the detected points into a line

How to connect is relatively simple, here we only need to set the dip range a bit larger when drawing the corner points, here is set to 5.

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

The following is the effect picture.
Insert picture description here
Just connect to achieve this effect.

3. Calculate the area of ​​each area according to the area divided by the line and get the largest area

Here, according to the principle of depth-first search , different areas are divided and the largest area is finally selected;

If you don’t know the depth-first search, you can refer to this article:
Basic Algorithm-Depth First Search (DFS) and Breadth First Search (BFS)

All areas are searched directly here. The area that accounts for the most pixels is displayed, and the effect is shown in the figure:
Insert picture description here

	/**根据线分割出的区域计算各区域面积,并得到最大面积
	 * @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;
	}

4. Select a coordinate point in the area of ​​the area as the result

Here we have found the largest area, just pick a point at will

In the above code

//改变最大区域颜色
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());
		}
	}
}

Change to the following code

//标记选取到的点
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;
	}
}

Result display:

Insert picture description here
This article's ideas reference: https://blog.csdn.net/aaronjny/article/details/110245896
Insert picture description here

Author: taro-flavored cat Dian
stamp here → Kankan your mobile phone number registered at how many sites! ! !
Friendly recommendation: a new generation of secure SMS

Guess you like

Origin blog.csdn.net/weixin_49701447/article/details/110627934