java识别简单的验证码
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)的技术被越来越广泛地运用到各个领域的软件系统当中.本文从业务的角度分析了单点登录的需求和应用领域:从技术本身的角度分析了单点登录技术的内部机制和实现 ...
随机推荐
- 初次使用Docker的体验笔记
一.前言 Docker容器已经发布许久,但作为一名程序员如今才开始接触,实在是罪过-- 在此之前,我还没有对Docker进行过深入的了解,对它的认识仍停留在:这是一种新型的虚拟机.这样的 ...
- XSLT
一.简介 XSLT 是一种用于将 XML 文档转换为 XHTML 文档或其他 XML 文档的语言. XSL(eXtensible Stylesheet Language) -- 可扩展标记语言,主要用 ...
- poj 3667 Hotel(线段树,区间合并)
Hotel Time Limit: 3000MSMemory Limit: 65536K Total Submissions: 10858Accepted: 4691 Description The ...
- POJ 2406 Power Strings (KMP)
Power Strings Time Limit: 3000MSMemory Limit: 65536K Total Submissions: 29663Accepted: 12387 Descrip ...
- 20150912华为机考2之"输入一段字符串(英文),将每个单词首字母大写后输出"
还有其他一些(隐性)要求(要不然无法通过测试): .如果首字母已经大写,则不用变 .不是英文字母的不变 e.g. Input: hello world! this is _Ljj speaking! ...
- TFS 2013”无法移除仍为团队管理员身份的标识”
由于开发人员的工作变动,在TFS 2013的日常维护中,经常需要将已经离开团队的成员账户移除出本团队项目. 一.将用户从团队成员中移除 一般情况下,只需要在团队项目的控制面板界面(控制面板>Co ...
- 【读书笔记《Android游戏编程之从零开始》】11.游戏开发基础(SurfaceView 游戏框架、View 和 SurfaceView 的区别)
1. SurfaceView 游戏框架实例 实例效果:就是屏幕上的文本跟着点击的地方移动,效果图如下: 步骤: 新建项目“GameSurfaceView”,首先自定义一个类"MySurfac ...
- Windows事件ID大全
51 Windows 无法找到网络路径.请确认网络路径正确并且目标计算机不忙或已关闭.如果 Windows 仍然无法找到网络路径,请与网络管理员联系. 52 由于网络上有重名,没有连接.请到“控制面板 ...
- smarty中三种变量的访问方式
在模板中smarty有三种变量,第一种,php分配的变量,第二种配置文件里的变量,第三种,PHP全局数组里的变量,配置文件里变量的访问方式可以是{#bgcolor#},"#"必须紧 ...
- 使用AdapterTypeRender对不同类型的item数据到UI的渲染
要实现聊天功能中的发送不同类型的信息,比如纯文本.图片.语音.图文混排多媒体的数据等(具体效果看微信). 这里使用AdapterTypeRender在BaseTypeAdapter(这个之后会讲到)中 ...