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. strcat()函数常见问题

    strcat(char *_Destination,const char *_Source)函数的功能是将后一个字符串粘贴到前一个字符串的末尾 原型 char *strcat(char *_Desti ...

  2. js追加元素,以及元素位置

    function setShow(val_param,text){ var ul = document.getElementById("copyhere"); //<li&g ...

  3. Astyle编程语言格式化工具的中文说明

    Artistic Style 1.23Maintained by: Jim PatteeOriginal Author: Tal Davidson Usage  :  astyle [options] ...

  4. 初学嵌入式STM32基础下选哪款开发板适合学习

    iTOP-4412开发板 目前为止,在用户网盘上已经积累了多达100G以上资料, 这些资料都是和4412相关的,并不是随便拼凑起来的!同时我们也完全开放原厂资料. 鉴于用户对于海量资料无从下手的问题, ...

  5. Java性能调优笔记

    Java性能调优笔记 调优步骤:衡量系统现状.设定调优目标.寻找性能瓶颈.性能调优.衡量是否到达目标(如果未到达目标,需重新寻找性能瓶颈).性能调优结束. 寻找性能瓶颈 性能瓶颈的表象:资源消耗过多. ...

  6. Docker与容器快速入门

    Docker之风席卷全球,但很多人觉得docker入门确实不太容易,其原因在于很多知识点上没准备好,在docker解决了什么问题.怎么解决的.用什么技术解决的都还没想清楚的时候就去探索docker组件 ...

  7. CUDA入门1

      1GPUs can handle thousands of concurrent threads. 2The pieces of code running on the gpu are calle ...

  8. 双向广搜 POJ 3126 Prime Path

      POJ 3126  Prime Path Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 16204   Accepted ...

  9. Tarjian算法求强联通分量

    如果两个顶点可以相互通达,则称两个顶点强连通(strongly connected).如果有向图G的每两个顶点都强连通,称G是一个强连通图.强连通图有向图的极大强连通子图,称为强连通分量(strong ...

  10. 如何查看windows xp系统的位数?

    1.右击“我的电脑”->属性,可以看到.2.运行dxdiag,在操作系统一行可以看到.3.运行cmd,输入systeminfo,在系统类型一栏可以看到.--简单4.使用一些检测软件也可以看,像鲁 ...