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识别简单的验证码的更多相关文章
-
java实现简单的验证码(待增强)
package com.xxx; import java.awt.Color;import java.awt.Font;import java.awt.Graphics2D;import java.a ...
-
Python——pytessercat识别简单的验证码
什么是验证码 验证码(CAPTCHA)是“Completely Automated Public Turing test to tell Computersand Humans Apart” (全自动 ...
-
Java使用Java OCR API进行验证码识别
Maven坐标: <!-- https://mvnrepository.com/artifact/com.asprise.ocr/java-ocr-api --> <dependen ...
-
基于Python使用SVM识别简单的字符验证码的完整代码开源分享
关键字:Python,SVM,字符验证码,机器学习,验证码识别 1 概述 基于Python使用SVM识别简单的验证字符串的完整代码开源分享. 因为目前有了更厉害的新技术来解决这类问题了,但是本文作 ...
-
java生成简单验证码图片
概要 最近项目需要用java实现输出随机验证码图片到前台,正好有机会接触下java的绘图类,完成需求后也有时间做个总结,写篇随笔记录下也希望能帮助到有同样需求的人! 需求流程图 1.生成随机数 在ja ...
-
使用TensorFlow 来实现一个简单的验证码识别过程
本文我们来用 TensorFlow 来实现一个深度学习模型,用来实现验证码识别的过程,这里识别的验证码是图形验证码,首先我们会用标注好的数据来训练一个模型,然后再用模型来实现这个验证码的识别. 1.验 ...
-
knn识别简单验证码
参考 https://www.biaodianfu.com/knn-captcha-recognition.html 内容大致一样,只是根据自己的想法加入了一些改动 KNN(k近邻算法) 算法原理请看 ...
-
Java模拟登录带验证码的教务系统(原理详解)
一:原理 客户端访问服务器,服务器通过Session对象记录会话,服务器可以指定一个唯一的session ID作为cookie来代表每个客户端,用来识别这个客户端接下来的请求. 我们通过Chrome浏 ...
-
java实现简单的单点登录
java实现简单的单点登录 摘要:单点登录(SSO)的技术被越来越广泛地运用到各个领域的软件系统当中.本文从业务的角度分析了单点登录的需求和应用领域:从技术本身的角度分析了单点登录技术的内部机制和实现 ...
随机推荐
-
UI控件(UISlider)
@implementation ViewController - (void)viewDidLoad { [super viewDidLoad]; UISlider* slider = [[UISli ...
-
【英语魔法俱乐部——读书笔记】 1 初级句型-简单句(Simple Sentences)
第一部分 1 初级句型-简单句(Simple Sentences):(1.1)基本句型&补语.(1.2)名词短语&冠词.(1.3)动词时态.(1.4)不定式短语.(1.5)动名词.(1 ...
-
[数据库]漫谈ElasticSearch关于ES性能调优几件必须知道的事(转)
ElasticSearch是现在技术前沿的大数据引擎,常见的组合有ES+Logstash+Kibana作为一套成熟的日志系统,其中Logstash是ETL工具,Kibana是数据分析展示平台.ES让人 ...
-
项目源码--JSP在线客服系统(SSH框架技术)源码
下载源码 技术要点: 1.网站开发技术框架 2.SSH技术框架(Struct,Spring,Hibrnate) 3.JSP技术框架 4.MYSQL数据库数据存储 5.即时通讯技术 6.源码带详细的中文 ...
-
hdu 4271 动态规划
思路:考的是字符串的编辑距离.在蓝桥杯2012年决赛上出现过. #include<iostream> #include<cstdio> #include<cstring& ...
-
后台字符串转化成json
function remotecontrol() { var progressbar = $("#progressbar"); $.ajax({ url: myurl, type: ...
-
JSP和servlet结合案例
[使用JSP技术实现猜数字游戏] 设计一个web app,有一个随机数字,给5次机会让客户猜测这个数字: 1)如果客户猜的数字比产生的数字值大,则提示"可惜,大了点". 2)如果客 ...
-
1.4. chromium源代码分析 - chromiumframe - 消息系列
Message framework 是对消息循环的封装和扩展,Chromium在消息循环中增加处理内部任务的工作.将内部工作处理寄生在Windows的消息循环中,会有一个问题,就是没有Windows自 ...
-
windows下更新python报错permission denied
注意退出所有python进程,可能是在使用中导致权限不足以删除
-
Java基本语法-----java运算符
这块的东西比较多 我写了太慢了 于是在word里写好贴出来供大家一起学习 运算符 -赋值运算符 -比较运算符 -逻辑运算符 -位运算符 -移位操作符 -三元运算符 [正在看本人博客的这位童鞋,我看你气 ...