1.老规矩,先上图
要破解类似这样的验证码:
拆分后结果:
然后去匹配,得到结果。
2.拆分图片
拿到图片后,首先把图片中我们需要的部分截取出来。
具体的做法是,创建一个的和图片像素相同的一个代表权重的二维数组,遍历图片的每个像素点,如果接近白色,就标记为1,否则标记为0;
然后遍历这个二维数据,如果一个竖排都1,说明是空白列,直到第一次遇到不全为1一列,记住列的下标作为起始值,再次遇到全为1的,记住下标作为结束值,然后从起始列到结束列截取图片,依次类推。
1 //分割图片
2 private Java.util.List<BufferedImage> splitImage(BufferedImage originImg)
3 throws Exception {
4 java.util.List<BufferedImage> subImgList = new ArrayList<>();
5 int height = originImg.getHeight();
6 int[][] weight = getImgWeight(originImg);
7 int start = 0;
8 int end = 0;
9 boolean isStartReady = false;
10 boolean isEndReady = false;
11 for (int i = 0; i < weight.length; i++) {
12 boolean isBlank = isBlankArr(weight[i]);
13 if (isBlank) {
14 if (isStartReady && !isEndReady) {
15 end = i;
16 isEndReady = true;
17 }
18 } else {
19 if (!isStartReady) {
20 start = i;
21 isStartReady = true;
22 }
23 }
24 if (isStartReady && isEndReady) {
25 subImgList.add(originImg.getSubimage(start, 0, end - start, height));
26 isStartReady = false;
27 isEndReady = false;
28 }
29 }
30 return subImgList;
31 }
32
33 //颜色是否为空白
34 private boolean isBlank(int colorInt) {
35 Color color = new Color(colorInt);
36 return color.getRed() + color.getGreen() + color.getBlue() > 600;
37 }
38
39 //数组是不是全空白
40 private boolean isBlankArr(int[] arr) {
41 boolean isBlank = true;
42 for (int value : arr) {
43 if (value == 0) {
44 isBlank = false;
45 break;
46 }
47 }
48 return isBlank;
49 }
50
51 //获取图片权重数据
52 private int[][] getImgWeight(BufferedImage img) {
53 int width = img.getWidth();
54 int height = img.getHeight();
55 int[][] weight = new int[width][height];
56 for (int x = 0; x < width; ++x) {
57 for (int y = 0; y < height; ++y) {
58 if (isBlank(img.getRGB(x, y))) {
59 weight[x][y] = 1;
60 }
61 }
62 }
63 return weight;
64 }
3.与拆分好的图片进行比较
拆分好的图片后,把拆分好的图片再次计算它的权重二维数据,加载之前准备好的"已知值的图片",也计算权重数组。
然后对比两个二维数组,如果大部分都匹配,就确定了值。
如果没有找到匹配的,就把图片保存下来,人工识别后放入已知值的图片组。