之前没有想过要通过爬取页面的方式来获取数据,想想毕竟api得到的数据有限,国内使用强智系统的不少,也算是做了点贡献吧。
识别的过程倒是蛮顺利。肉眼验证似乎没有不正确的
话不多说,我们看到的登录界面的验证码是这样的:

如果你的目标和这个一毛一样,那么你便可以拿来用咯
思路很清晰,首先我们知道图像实际上是个二维数组,我们将图片二值化,即处理成只有黑白两色的图像,与训练好的的二维数组逐一相比较,最接近哪个便是哪个字符。
如字母a的二维数组:

//a{{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},{0,0,0,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0},{0,0,1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0},{0,0,1,0,0,0,0,1,1,1,1,0,0,0,0,0,0,0,0,0},{0,0,0,0,0,0,0,0,1,1,1,0,0,0,0,0,0,0,0,0},{0,0,0,0,0,0,0,0,1,1,1,0,0,0,0,0,0,0,0,0},{0,0,0,0,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0},{0,0,1,1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0},{0,1,1,1,1,0,0,0,1,1,1,0,0,0,0,0,0,0,0,0},{0,1,1,1,0,0,0,0,1,1,1,0,0,0,0,0,0,0,0,0},{0,1,1,1,0,0,0,0,1,1,1,0,0,0,0,0,0,0,0,0},{0,1,1,1,0,0,0,1,1,1,1,0,0,0,0,0,0,0,0,0},{0,0,1,1,1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0},{0,0,0,1,1,1,1,0,0,1,1,1,0,0,0,0,0,0,0,0},{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}}

图片分析

验证码形如,经过爬取大量验证码可以发现,验证码图片为80*40px,周围有1px黑边,实际上黑边我忽略了,因为再后面的切割中被剪掉了。接着说图片,图片只含有小写字母和数字,没有字母o和数字0,即一共34个字符,后期要至少准备34个二维数组用于比较

进一步分析

打开ps

找一个图片有重合的例子,发现每个字符占水平20px,垂直24px,可以初步处理下,裁剪掉上下的空白:

BufferedImage image = ImageIO.read(f);
image = image.getSubimage(0, 9, 80, 24);

二值化

 public static BufferedImage grayImage(BufferedImage bufferedImage) throws Exception {int width = bufferedImage.getWidth();int height = bufferedImage.getHeight();BufferedImage grayBufferedImage = new BufferedImage(width, height, bufferedImage.getType());for (int i = 0; i < bufferedImage.getWidth(); i++) {for (int j = 0; j < bufferedImage.getHeight(); j++) {final int color = bufferedImage.getRGB(i, j);final int r = (color >> 16) & 0xff;final int g = (color >> 8) & 0xff;final int b = color & 0xff;int gray = (int) (0.3 * r + 0.59 * g + 0.11 * b);int newPixel = colorToRGB(255, gray, gray, gray);grayBufferedImage.setRGB(i, j, newPixel);}}return grayBufferedImage;}/*** 颜色分量转换为RGB值* * @param alpha* @param red* @param green* @param blue* @return*/private static int colorToRGB(int alpha, int red, int green, int blue) {int newPixel = 0;newPixel += alpha;newPixel = newPixel << 8;newPixel += red;newPixel = newPixel << 8;newPixel += green;newPixel = newPixel << 8;newPixel += blue;return newPixel;}public static BufferedImage binaryImage(BufferedImage image) throws Exception {int w = image.getWidth();int h = image.getHeight();float[] rgb = new float[3];double[][] coordinates = new double[w][h];int black = new Color(0, 0, 0).getRGB();int white = new Color(255, 255, 255).getRGB();BufferedImage bi = new BufferedImage(w, h, BufferedImage.TYPE_BYTE_BINARY);;for (int x = 0; x < w; x++) {for (int y = 0; y < h; y++) {int pixel = image.getRGB(x, y);rgb[0] = (pixel & 0xff0000) >> 16;rgb[1] = (pixel & 0xff00) >> 8;rgb[2] = (pixel & 0xff);float avg = (rgb[0] + rgb[1] + rgb[2]) / 3;coordinates[x][y] = avg;}}// 这里是阈值,白底黑字还是黑底白字,大多数情况下建议白底黑字,后面都以白底黑字为例double SW = 192;for (int x = 0; x < w; x++) {for (int y = 0; y < h; y++) {if (coordinates[x][y] < SW) {bi.setRGB(x, y, black);} else {bi.setRGB(x, y, white);}}}return bi;}

按照前面的分析将图片分割成4部分,分别处理之:

     int width = image.getWidth();int height = image.getHeight();//System.out.println("width\t" + width + "\theight\t" + height);//int subWidth = width / 4;newim[0] = binaryImage(image.getSubimage(4, 0, 20, height));newim[1] = binaryImage(image.getSubimage(22, 0, 20, height));newim[2] = binaryImage(image.getSubimage(40, 0, 20, height));newim[3] = binaryImage(image.getSubimage(58, 0, 20, height));

实际上现在每个分割的图片便可以用0,1表示,如果用██填充的话。。。

    ████████████                        ██████████████████                    ██          ████████                  ██████                  ██████                  ██████                  ██████                    ██████                      ████████████                        ████████████████                    ████████                  ████████                ██████                ██████                ██████                ████          ██████                  ██████████████████                    ██████████████                      {{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1},{0,0,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0},{0,1,1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0},{0,1,0,0,0,0,0,1,1,1,1,0,0,0,0,0,0,0,0,0},{0,0,0,0,0,0,0,0,1,1,1,0,0,0,0,0,0,0,0,0},{0,0,0,0,0,0,0,0,1,1,1,0,0,0,0,0,0,0,0,0},{0,0,0,0,0,0,0,0,1,1,1,0,0,0,0,0,0,0,0,0},{0,0,0,0,0,0,0,1,1,1,0,0,0,0,0,0,0,0,0,0},{0,0,0,0,0,0,1,1,1,0,0,0,0,0,0,0,0,0,0,0},{0,0,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0},{0,0,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0},{0,0,0,0,0,0,0,1,1,1,1,0,0,0,0,0,0,0,0,0},{0,0,0,0,0,0,0,0,1,1,1,1,0,0,0,0,0,0,0,0},{0,0,0,0,0,0,0,0,0,1,1,1,0,0,0,0,0,0,0,0},{0,0,0,0,0,0,0,0,0,1,1,1,0,0,0,0,0,0,0,0},{0,0,0,0,0,0,0,0,0,1,1,1,0,0,0,0,0,0,0,0},{0,1,1,0,0,0,0,0,1,1,1,0,0,0,0,0,0,0,0,0},{0,1,0,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0},{0,0,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0},{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}},

之后我们用训练好的数组比较选出结果即可

     StringBuilder sb = new StringBuilder();int count = -1;double total = 1;int hit = 0;while (++count < 4) {int chCount = 0;int target = 0;//最接近的指针double temp = -1.0;while (chCount < MyCharacter.g.length) {total = 1;hit = 0;for (int i = 0; i < g[count].length; i++) {for (int j = 0; j < g[count][i].length; j++) {if (MyCharacter.g[chCount][i][j] == 1) {//System.out.print("-");++total;if(g[count][i][j] == MyCharacter.g[chCount][i][j]) {//System.out.print("+");++hit;}}}}//System.out.println(hit);//System.out.println(total);//System.out.println(MyCharacter.ch[chCount]+" "+hit/total);if(hit/total > temp) {target = chCount;temp = hit/total;}else {}++chCount;}//比例最大的给他sb.append(MyCharacter.ch[target]);}return sb.toString();

效果不错

完整代码:github

参考: java图像处理

强智教务系统验证码识别 java相关推荐

  1. 强智教务系统API学习进度条--(以完结)

    前言 想写一个基于微信公众号的课表及成绩查询系统,记录学习过程与实现. 开发环境 IDEA JDK1.8 强智教务系统API文档 API目录 登录 (以实现) 时间信息 (以实现) 课程信息 成绩信息 ...

  2. 强智科技教务系统验证码识别

    强智科技验证码识别 前言 由于近期在写一个教务系统的爬虫程序,但是网站的验证码让人很头疼,所以笔者临时找了一些资料学习了一下,本人python用的很少,而且在机器学习这块也是新手,从来没有接触过,所以 ...

  3. 每日获取强智教务系统课表,并发送短信到学生手机!爬虫真牛逼!

    自从学校换了强智的教务系统后,学校的app的查课表功能基本就报废了,记不住课表的我无奈自己动手. 功能实现:如果当天有课,在当天早上6点30以短信的形式自动发送课表至手机 首先我想的是利用模拟登陆然后 ...

  4. 强智教务系统——获取课表

    两个接口: 获取个人信息以及登录成功后header中的token: http://jwxt.xxx.edu.cn/app.do?method=authUser&xh={$学号}&pwd ...

  5. python3 + selenium 进行强智教务成绩的刷新以及通知成绩(华东理工大学 某ecust)

    强智教务自动刷新教务处成绩,更新后发邮件通知,以某ECUST华理为例子.此处的ECUST华理教务系统是18年9月后的新系统 Windows端或者挂在阿里云上都可以,下文示例是在Ubuntu上运行的. ...

  6. 正方教务系统验证码自动识别(非打码平台)

    本人用的是网上的Java版本,经过本人的改良只剩下验证码识别. 详细说明请看  http://www.unique-liu.com/181.html ImagePreProcess.srcPath = ...

  7. 验证码识别 java 深度学习_使用深度学习识别验证码注解

    前言 在抓取一些网站的时候难免会遇到一些验证码.想起去年接触过一段时间的验证码识别技术,所以把之前使用的开源的cnn识别再拿出来做个注解.加深理解,也方便以后的使用.希望能对大家有所帮助! 正文 网上 ...

  8. 滑块验证码识别 java版本

    https://blog.csdn.net/qq_19383667/article/details/77879895 好久没有更新技术文章了,很久之前研究过滑块验证码的破解,照着别人的代码改,将其他版 ...

  9. 模拟教务评教(强智教务)—一件评教实现原理

    前言 前不久,学校有个校园帮助型app某某圈因为一件评教功能被教务批评了.现在有很多查成绩,查课程的app,他们的实现原理到底是啥了.这两天来到发小扬州这边,学习实现了这个功能,并且用java和pyt ...

  10. 滑块验证码识别 java版本

    好久没有更新技术文章了,很久之前研究过滑块验证码的破解,照着别人的代码改,将其他版本的代码改成java的,加上自己的一些研究,凑合凑合出了第一个java版本的,此版本不是控制浏览器进行验证,纯java ...

最新文章

  1. 移民澳洲好网站http://home.hexun.com/ausky/default.html
  2. 進階查詢,讓查詢條件精確到底...
  3. Git Rebase教程: 用Git Rebase让时光倒流
  4. USTC English Club Note20171023(2)
  5. 爆牙齿的世界杯日记(阿根疼啦)
  6. ASP.NetCore+VUE 实现学生成绩管理系统(一)
  7. 【转】用fo-dicom实现print scu的注意事项!!!!!!!!!
  8. java 反射获取对象_使用Java反射机制获取对象
  9. 交互系统的构建之(一)重写Makefile编译TLD系统
  10. 住150平米以上的房子是怎样一种体验?
  11. centos7 安装python3.6 及模块安装演示
  12. Levenshtein编辑距离C++实现
  13. Train Problem I(STL)基本运用stack
  14. 最短哈密尔顿圈matlab解法_数学建模学习笔记
  15. 小程序 蓝牙连接(出现的问题和一些解决方法)
  16. 炮兵阵地图文详解NOI2001/POJ1185(状态压缩)
  17. 360安全浏览器总是锁屏解锁后自启动打开网页,烦~
  18. C语言readdir()函数:读取目录函数
  19. 零知识证明学习资源汇总
  20. sequoia负载均衡

热门文章

  1. JavaScript 每日一题 #6
  2. Spanning Tree协议安全攻防
  3. word文档中标题跳到表格的下方-解决方法
  4. 移动研发平台EMAS 3.0全新升级,欢迎登陆阿里云官网搜索EMAS进行体验
  5. html5 邮箱后缀自动填写,JS输入用户名自动显示邮箱后缀列表的方法
  6. python代码情话_python教你谈恋爱-之-土味情话5000条
  7. 用c语言编写出的情话,c语言for情话
  8. 引流又增效,跨境电商必备的宝藏工具
  9. Java企业工商信息查询
  10. 系统重温Pandas笔记:(五)变形