1.老规矩,先上图

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

拆分后结果:

然后去匹配,得到结果。

2.拆分图片

拿到图片后,首先把图片中我们需要的部分截取出来。

具体的做法是,创建一个的和图片像素相同的一个代表权重的二维数组,遍历图片的每个像素点,如果接近白色,就标记为1,否则标记为0;

然后遍历这个二维数据,如果一个竖排都1,说明是空白列,直到第一次遇到不全为1一列,记住列的下标作为起始值,再次遇到全为1的,记住下标作为结束值,然后从起始列到结束列截取图片,依次类推。

   //分割图片
     private java.util.List<BufferedImage> splitImage(BufferedImage originImg)
             throws Exception {
         java.util.List<BufferedImage> subImgList = new ArrayList<>();
         int height = originImg.getHeight();
         int[][] weight = getImgWeight(originImg);
         int start = 0;
         int end = 0;
         boolean isStartReady = false;
         boolean isEndReady = false;
         for (int i = 0; i < weight.length; i++) {
             boolean isBlank = isBlankArr(weight[i]);
             if (isBlank) {
                 if (isStartReady && !isEndReady) {
                     end = i;
                     isEndReady = true;
                 }
             } else {
                 if (!isStartReady) {
                     start = i;
                     isStartReady = true;
                 }
             }
             if (isStartReady && isEndReady) {
                 subImgList.add(originImg.getSubimage(start, 0, end - start, height));
                 isStartReady = false;
                 isEndReady = false;
             }
         }
         return subImgList;
     }

     //颜色是否为空白
     private boolean isBlank(int colorInt) {
         Color color = new Color(colorInt);
         return color.getRed() + color.getGreen() + color.getBlue() > 600;
     }

     //数组是不是全空白
     private boolean isBlankArr(int[] arr) {
         boolean isBlank = true;
         for (int value : arr) {
             if (value == 0) {
                 isBlank = false;
                 break;
             }
         }
         return isBlank;
     }

     //获取图片权重数据
     private int[][] getImgWeight(BufferedImage img) {
         int width = img.getWidth();
         int height = img.getHeight();
         int[][] weight = new int[width][height];
         for (int x = 0; x < width; ++x) {
             for (int y = 0; y < height; ++y) {
                 if (isBlank(img.getRGB(x, y))) {
                     weight[x][y] = 1;
                 }
             }
         }
         return weight;
     }

3.与拆分好的图片进行比较

拆分好的图片后,把拆分好的图片再次计算它的权重二维数据,加载之前准备好的"已知值的图片",也计算权重数组。

然后对比两个二维数组,如果大部分都匹配,就确定了值。

如果没有找到匹配的,就把图片保存下来,人工识别后放入已知值的图片组。

   //分析识别
     private String realize(java.util.List<BufferedImage> imgList) {
         String resultStr = "";
         for (BufferedImage img : imgList) {
             String key = getKey(Global.trainedMap, img);
             if (key == null) {
                 String noTrainedKey = getKey(Global.noTrainedMap, img);
                 if(noTrainedKey == null){
                     try {
                         ImageIO.write(img, "JPG", new File(Global.LIB_NO + File.separator + UUID.randomUUID() + ".jpg"));
                     } catch (IOException e) {
                         e.printStackTrace();
                     }
                 }
             } else {
                 resultStr += key;
             }
         }
         return resultStr;
     }

     //获取已知值
     private String getKey(Map<String, BufferedImage> map, BufferedImage img){
         String resultStr = null;
         Set<Map.Entry<String, BufferedImage>> entrySet = map.entrySet();
         for (Map.Entry<String, BufferedImage> one : entrySet) {
             if (isSimilarity(img, one.getValue())) {
                 resultStr = one.getKey();
                 break;
             }
         }
         return resultStr;
     }

     //是否相似
     private boolean isSimilarity(BufferedImage imageA, BufferedImage imageB) {
         int widthA = imageA.getWidth();
         int widthB = imageB.getWidth();
         int heightA = imageA.getHeight();
         int heightB = imageB.getHeight();
         if (widthA != widthB || heightA != heightB) {
             return false;
         } else {
             int[][] weightA = getImgWeight(imageA);
             int[][] weightB = getImgWeight(imageB);
             int count = 0;
             for (int i = 0; i < widthA; i++) {
                 for (int j = 0; j < heightB; j++) {
                     if (weightA[i][j] != weightB[i][j]) {
                         count++;
                     }
                 }
             }
             if ((double) count / (widthA * widthB) > (1 - Global.SIMILARITY)) {
                 return false;
             } else {
                 return true;
             }
         }
     }

4.完整代码

 import javax.imageio.ImageIO;
 import java.awt.image.BufferedImage;
 import java.io.File;
 import java.io.IOException;
 import java.util.HashMap;
 import java.util.Map;

 public class Global {
     public static final String LIB_PATH = "C:/lib";
     public static final String LIB_NO = "C:/no";
     public static final double SIMILARITY = 0.9;
     public static Map<String, BufferedImage> trainedMap;
     public static Map<String, BufferedImage> noTrainedMap = new HashMap<>();

     static {
         trainedMap = getMap(LIB_PATH);
         noTrainedMap = getMap(LIB_NO);
     }

     private static Map<String, BufferedImage>  getMap(String path) {
        Map<String, BufferedImage> map = new HashMap<>();
         File parentFile = new File(path);
         for (String filePath : parentFile.list()) {
             File file = new File(path + File.separator + filePath);
             String fileName = file.getName();
             String key = fileName.substring(0,fileName.indexOf(".")).trim();
             try {
                 map.put(key, ImageIO.read(file));
             } catch (IOException e) {
                 e.printStackTrace();
             }
         }
         return map;
     }
 }
 import javax.imageio.ImageIO;
 import java.awt.*;
 import java.awt.image.BufferedImage;
 import java.io.File;
 import java.io.IOException;
 import java.util.*;

 /**
  * 识别验证码
  */
 public class ImageProcess {
     private String imgPath;

     public ImageProcess(String imgPath) {
         this.imgPath = imgPath;
     }

     public String getResult() {
         java.util.List<BufferedImage> imgList = null;
         try {
             BufferedImage img = ImageIO.read(new File(imgPath));
             imgList = splitImage(img);
         } catch (IOException e) {
             e.printStackTrace();
         } catch (Exception e) {
             e.printStackTrace();
         }
         return realize(imgList);
     }

     //分析识别
     private String realize(java.util.List<BufferedImage> imgList) {
         String resultStr = "";
         for (BufferedImage img : imgList) {
             String key = getKey(Global.trainedMap, img);
             if (key == null) {
                 String noTrainedKey = getKey(Global.noTrainedMap, img);
                 if(noTrainedKey == null){
                     try {
                         ImageIO.write(img, "JPG", new File(Global.LIB_NO + File.separator + UUID.randomUUID() + ".jpg"));
                     } catch (IOException e) {
                         e.printStackTrace();
                     }
                 }
             } else {
                 resultStr += key;
             }
         }
         return resultStr;
     }

     //获取已知值
     private String getKey(Map<String, BufferedImage> map, BufferedImage img){
         String resultStr = null;
         Set<Map.Entry<String, BufferedImage>> entrySet = map.entrySet();
         for (Map.Entry<String, BufferedImage> one : entrySet) {
             if (isSimilarity(img, one.getValue())) {
                 resultStr = one.getKey();
                 break;
             }
         }
         return resultStr;
     }

     //是否相似
     private boolean isSimilarity(BufferedImage imageA, BufferedImage imageB) {
         int widthA = imageA.getWidth();
         int widthB = imageB.getWidth();
         int heightA = imageA.getHeight();
         int heightB = imageB.getHeight();
         if (widthA != widthB || heightA != heightB) {
             return false;
         } else {
             int[][] weightA = getImgWeight(imageA);
             int[][] weightB = getImgWeight(imageB);
             int count = 0;
             for (int i = 0; i < widthA; i++) {
                 for (int j = 0; j < heightB; j++) {
                     if (weightA[i][j] != weightB[i][j]) {
                         count++;
                     }
                 }
             }
             if ((double) count / (widthA * widthB) > (1 - Global.SIMILARITY)) {
                 return false;
             } else {
                 return true;
             }
         }
     }

     //分割图片
     private java.util.List<BufferedImage> splitImage(BufferedImage originImg)
             throws Exception {
         java.util.List<BufferedImage> subImgList = new ArrayList<>();
         int height = originImg.getHeight();
         int[][] weight = getImgWeight(originImg);
         int start = 0;
         int end = 0;
         boolean isStartReady = false;
         boolean isEndReady = false;
         for (int i = 0; i < weight.length; i++) {
             boolean isBlank = isBlankArr(weight[i]);
             if (isBlank) {
                 if (isStartReady && !isEndReady) {
                     end = i;
                     isEndReady = true;
                 }
             } else {
                 if (!isStartReady) {
                     start = i;
                     isStartReady = true;
                 }
             }
             if (isStartReady && isEndReady) {
                 subImgList.add(originImg.getSubimage(start, 0, end - start, height));
                 isStartReady = false;
                 isEndReady = false;
             }
         }
         return subImgList;
     }

     //颜色是否为空白
     private boolean isBlank(int colorInt) {
         Color color = new Color(colorInt);
         return color.getRed() + color.getGreen() + color.getBlue() > 600;
     }

     //数组是不是全空白
     private boolean isBlankArr(int[] arr) {
         boolean isBlank = true;
         for (int value : arr) {
             if (value == 0) {
                 isBlank = false;
                 break;
             }
         }
         return isBlank;
     }

     //获取图片权重数据
     private int[][] getImgWeight(BufferedImage img) {
         int width = img.getWidth();
         int height = img.getHeight();
         int[][] weight = new int[width][height];
         for (int x = 0; x < width; ++x) {
             for (int y = 0; y < height; ++y) {
                 if (isBlank(img.getRGB(x, y))) {
                     weight[x][y] = 1;
                 }
             }
         }
         return weight;
     }

     public static void main(String[] args) throws Exception {
         String result = new ImageProcess("C:/login.jpg").getResult();
         System.out.println(result);

     }
 }

java识别简单的验证码的更多相关文章

  1. java实现简单的验证码(待增强)

    package com.xxx; import java.awt.Color;import java.awt.Font;import java.awt.Graphics2D;import java.a ...

  2. Python——pytessercat识别简单的验证码

    什么是验证码 验证码(CAPTCHA)是“Completely Automated Public Turing test to tell Computersand Humans Apart” (全自动 ...

  3. Java使用Java OCR API进行验证码识别

    Maven坐标: <!-- https://mvnrepository.com/artifact/com.asprise.ocr/java-ocr-api --> <dependen ...

  4. 基于Python使用SVM识别简单的字符验证码的完整代码开源分享

    关键字:Python,SVM,字符验证码,机器学习,验证码识别 1   概述 基于Python使用SVM识别简单的验证字符串的完整代码开源分享. 因为目前有了更厉害的新技术来解决这类问题了,但是本文作 ...

  5. java生成简单验证码图片

    概要 最近项目需要用java实现输出随机验证码图片到前台,正好有机会接触下java的绘图类,完成需求后也有时间做个总结,写篇随笔记录下也希望能帮助到有同样需求的人! 需求流程图 1.生成随机数 在ja ...

  6. 使用TensorFlow 来实现一个简单的验证码识别过程

    本文我们来用 TensorFlow 来实现一个深度学习模型,用来实现验证码识别的过程,这里识别的验证码是图形验证码,首先我们会用标注好的数据来训练一个模型,然后再用模型来实现这个验证码的识别. 1.验 ...

  7. knn识别简单验证码

    参考 https://www.biaodianfu.com/knn-captcha-recognition.html 内容大致一样,只是根据自己的想法加入了一些改动 KNN(k近邻算法) 算法原理请看 ...

  8. Java模拟登录带验证码的教务系统(原理详解)

    一:原理 客户端访问服务器,服务器通过Session对象记录会话,服务器可以指定一个唯一的session ID作为cookie来代表每个客户端,用来识别这个客户端接下来的请求. 我们通过Chrome浏 ...

  9. java实现简单的单点登录

    java实现简单的单点登录 摘要:单点登录(SSO)的技术被越来越广泛地运用到各个领域的软件系统当中.本文从业务的角度分析了单点登录的需求和应用领域:从技术本身的角度分析了单点登录技术的内部机制和实现 ...

随机推荐

  1. Bootstrap(转)

    Bootstrap 随着互联网的不断成熟以及我们越来越多的用各种移动端的设备访问互联网,Web设计师和Web开发者的工作也变得越来越复杂. 十年前,一切都还简单得多.那个时候,大部分用户都是坐在桌子前 ...

  2. cocos2d-x之物理引擎之碰撞监测

    #include "HelloWorldScene.h" USING_NS_CC; #define RED_BIT_MASK    0b0100 #define GREEN_BIT ...

  3. 烂泥:LVM学习之逻辑卷、卷组及物理卷删除

    本文由秀依林枫提供友情赞助,首发于烂泥行天下. 上篇文章,我们介绍了有关LVM的逻辑卷及卷组的空间缩小.这次我们来介绍下如何删除一个逻辑卷及卷组. 删除逻辑卷需要以下几个步骤: 1. 卸载已经挂载的逻 ...

  4. Node.js的模块载入方式与机制

    Node.js中模块可以通过文件路径或名字获取模块的引用.模块的引用会映射到一个js文件路径,除非它是一个Node内置模块.Node的内置模块公开了一些常用的API给开发者,并且它们在Node进程开始 ...

  5. poj 3169 Layout 差分约束模板题

    Layout Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 6415   Accepted: 3098 Descriptio ...

  6. Hadoop_HDFS文件读写代码流程解析和副本存放机制

    Hadoop学习笔记总结 01.RPC(远程过程调用) 1. RPC概念 远程过程指的不是同一个进程的调用.它是一种通过网络从远程计算机程序上请求服务,而不需要了解底层网络技术的协议. 不能直接拿到远 ...

  7. #include <NOIP2008 Junior> 双栈排序 ——using namespace wxl;

    题目描述 Tom最近在研究一个有趣的排序问题.如图所示,通过2个栈S1和S2,Tom希望借助以下4种操作实现将输入序列升序排序. 操作a 如果输入序列不为空,将第一个元素压入栈S1 操作b 如果栈S1 ...

  8. Golang gRPC 示例

    1.安装gRPC runtime go get google.golang.org/grpc 为了自动生成Golang的gRPC代码,需要安装protocal buffers compiler以及对应 ...

  9. 《TCP/IP详解 卷一》读书笔记-----UDP&IP 分片

    1.进程每产生一个UDP数据报就由一个IP数据报进行发送,而在TCP中,一个IP数据报并不与每个TCP报文段一一对应 2.UDP的端口号和TCP的端口号是相互独立的,对那些众所周知的端口号TCP和UD ...

  10. 《EXO指数型组织》阅读脑图

    书籍:<EXO指数型组织:打造独角兽公司的11个最强属性> 预览链接:https://www.processon.com/view/link/57ce8279e4b08cbf6ca8f85 ...