手机版
你好,游客 登录 注册
背景:
阅读新闻

Java识别简单的验证码

[日期:2015-09-13] 来源:Linux社区  作者:xiaoxiaoyiran [字体: ]

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 }

本文永久更新链接地址http://www.linuxidc.com/Linux/2015-09/122965.htm

linux
相关资讯       Java验证码识别 
本文评论   查看全部评论 (0)
表情: 表情 姓名: 字数

       

评论声明
  • 尊重网上道德,遵守中华人民共和国的各项有关法律法规
  • 承担一切因您的行为而直接或间接导致的民事或刑事法律责任
  • 本站管理人员有权保留或删除其管辖留言中的任意内容
  • 本站有权在网站内转载或引用您的评论
  • 参与本评论即表明您已经阅读并接受上述条款