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.与拆分好的图片进行比较
拆分好的图片后,把拆分好的图片再次计算它的权重二维数据,加载之前准备好的"已知值的图片",也计算权重数组。
然后对比两个二维数组,如果大部分都匹配,就确定了值。
如果没有找到匹配的,就把图片保存下来,人工识别后放入已知值的图片组。
1 //分析识别
2 private String realize(java.util.List<BufferedImage> imgList) {
3 String resultStr = "";
4 for (BufferedImage img : imgList) {
5 String key = getKey(Global.trainedMap, img);
6 if (key == null) {
7 String noTrainedKey = getKey(Global.noTrainedMap, img);
8 if(noTrainedKey == null){
9 try {
10 ImageIO.write(img, "JPG", new File(Global.LIB_NO + File.separator + UUID.randomUUID() + ".jpg"));
11 } catch (IOException e) {
12 e.printStackTrace();
13 }
14 }
15 } else {
16 resultStr += key;
17 }
18 }
19 return resultStr;
20 }
21
22 //获取已知值
23 private String getKey(Map<String, BufferedImage> map, BufferedImage img){
24 String resultStr = null;
25 Set<Map.Entry<String, BufferedImage>> entrySet = map.entrySet();
26 for (Map.Entry<String, BufferedImage> one : entrySet) {
27 if (isSimilarity(img, one.getValue())) {
28 resultStr = one.getKey();
29 break;
30 }
31 }
32 return resultStr;
33 }
34
35 //是否相似
36 private boolean isSimilarity(BufferedImage imageA, BufferedImage imageB) {
37 int widthA = imageA.getWidth();
38 int widthB = imageB.getWidth();
39 int heightA = imageA.getHeight();
40 int heightB = imageB.getHeight();
41 if (widthA != widthB || heightA != heightB) {
42 return false;
43 } else {
44 int[][] weightA = getImgWeight(imageA);
45 int[][] weightB = getImgWeight(imageB);
46 int count = 0;
47 for (int i = 0; i < widthA; i++) {
48 for (int j = 0; j < heightB; j++) {
49 if (weightA[i][j] != weightB[i][j]) {
50 count++;
51 }
52 }
53 }
54 if ((double) count / (widthA * widthB) > (1 - Global.SIMILARITY)) {
55 return false;
56 } else {
57 return true;
58 }
59 }
60 }
4.完整代码
1 import javax.imageio.ImageIO;
2 import java.awt.image.BufferedImage;
3 import java.io.File;
4 import java.io.IOException;
5 import java.util.HashMap;
6 import java.util.Map;
7
8 public class Global {
9 public static final String LIB_PATH = "C:/lib";
10 public static final String LIB_NO = "C:/no";
11 public static final double SIMILARITY = 0.9;
12 public static Map<String, BufferedImage> trainedMap;
13 public static Map<String, BufferedImage> noTrainedMap = new HashMap<>();
14
15 static {
16 trainedMap = getMap(LIB_PATH);
17 noTrainedMap = getMap(LIB_NO);
18 }
19
20 private static Map<String, BufferedImage> getMap(String path) {
21 Map<String, BufferedImage> map = new HashMap<>();
22 File parentFile = new File(path);
23 for (String filePath : parentFile.list()) {
24 File file = new File(path + File.separator + filePath);
25 String fileName = file.getName();
26 String key = fileName.substring(0,fileName.indexOf(".")).trim();
27 try {
28 map.put(key, ImageIO.read(file));
29 } catch (IOException e) {
30 e.printStackTrace();
31 }
32 }
33 return map;
34 }
35 }
36 import javax.imageio.ImageIO;
37 import java.awt.*;
38 import java.awt.image.BufferedImage;
39 import java.io.File;
40 import java.io.IOException;
41 import java.util.*;
42
43 /**
44 * 识别验证码
45 */
46 public class ImageProcess {
47 private String imgPath;
48
49 public ImageProcess(String imgPath) {
50 this.imgPath = imgPath;
51 }
52
53 public String getResult() {
54 java.util.List<BufferedImage> imgList = null;
55 try {
56 BufferedImage img = ImageIO.read(new File(imgPath));
57 imgList = splitImage(img);
58 } catch (IOException e) {
59 e.printStackTrace();
60 } catch (Exception e) {
61 e.printStackTrace();
62 }
63 return realize(imgList);
64 }
65
66 //分析识别
67 private String realize(java.util.List<BufferedImage> imgList) {
68 String resultStr = "";
69 for (BufferedImage img : imgList) {
70 String key = getKey(Global.trainedMap, img);
71 if (key == null) {
72 String noTrainedKey = getKey(Global.noTrainedMap, img);
73 if(noTrainedKey == null){
74 try {
75 ImageIO.write(img, "JPG", new File(Global.LIB_NO + File.separator + UUID.randomUUID() + ".jpg"));
76 } catch (IOException e) {
77 e.printStackTrace();
78 }
79 }
80 } else {
81 resultStr += key;
82 }
83 }
84 return resultStr;
85 }
86
87 //获取已知值
88 private String getKey(Map<String, BufferedImage> map, BufferedImage img){
89 String resultStr = null;
90 Set<Map.Entry<String, BufferedImage>> entrySet = map.entrySet();
91 for (Map.Entry<String, BufferedImage> one : entrySet) {
92 if (isSimilarity(img, one.getValue())) {
93 resultStr = one.getKey();
94 break;
95 }
96 }
97 return resultStr;
98 }
99
100 //是否相似
101 private boolean isSimilarity(BufferedImage imageA, BufferedImage imageB) {
102 int widthA = imageA.getWidth();
103 int widthB = imageB.getWidth();
104 int heightA = imageA.getHeight();
105 int heightB = imageB.getHeight();
106 if (widthA != widthB || heightA != heightB) {
107 return false;
108 } else {
109 int[][] weightA = getImgWeight(imageA);
110 int[][] weightB = getImgWeight(imageB);
111 int count = 0;
112 for (int i = 0; i < widthA; i++) {
113 for (int j = 0; j < heightB; j++) {
114 if (weightA[i][j] != weightB[i][j]) {
115 count++;
116 }
117 }
118 }
119 if ((double) count / (widthA * widthB) > (1 - Global.SIMILARITY)) {
120 return false;
121 } else {
122 return true;
123 }
124 }
125 }
126
127 //分割图片
128 private java.util.List<BufferedImage> splitImage(BufferedImage originImg)
129 throws Exception {
130 java.util.List<BufferedImage> subImgList = new ArrayList<>();
131 int height = originImg.getHeight();
132 int[][] weight = getImgWeight(originImg);
133 int start = 0;
134 int end = 0;
135 boolean isStartReady = false;
136 boolean isEndReady = false;
137 for (int i = 0; i < weight.length; i++) {
138 boolean isBlank = isBlankArr(weight[i]);
139 if (isBlank) {
140 if (isStartReady && !isEndReady) {
141 end = i;
142 isEndReady = true;
143 }
144 } else {
145 if (!isStartReady) {
146 start = i;
147 isStartReady = true;
148 }
149 }
150 if (isStartReady && isEndReady) {
151 subImgList.add(originImg.getSubimage(start, 0, end - start, height));
152 isStartReady = false;
153 isEndReady = false;
154 }
155 }
156 return subImgList;
157 }
158
159 //颜色是否为空白
160 private boolean isBlank(int colorInt) {
161 Color color = new Color(colorInt);
162 return color.getRed() + color.getGreen() + color.getBlue() > 600;
163 }
164
165 //数组是不是全空白
166 private boolean isBlankArr(int[] arr) {
167 boolean isBlank = true;
168 for (int value : arr) {
169 if (value == 0) {
170 isBlank = false;
171 break;
172 }
173 }
174 return isBlank;
175 }
176
177 //获取图片权重数据
178 private int[][] getImgWeight(BufferedImage img) {
179 int width = img.getWidth();
180 int height = img.getHeight();
181 int[][] weight = new int[width][height];
182 for (int x = 0; x < width; ++x) {
183 for (int y = 0; y < height; ++y) {
184 if (isBlank(img.getRGB(x, y))) {
185 weight[x][y] = 1;
186 }
187 }
188 }
189 return weight;
190 }
191
192
193 public static void main(String[] args) throws Exception {
194 String result = new ImageProcess("C:/login.jpg").getResult();
195 System.out.println(result);
196
197 }
198 }

本文链接:java识别简单的验证码,转载请注明。