转载

java识别简单的验证码

1.老规矩,先上图

要破解类似这样的验证码:

java识别简单的验证码

拆分后结果:

java识别简单的验证码

然后去匹配,得到结果。

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 }
正文到此结束
Loading...