昨天发现的了一段非常令人惊奇的JavaScript代码,是由ShaunF编写的automatically solves captchas,一个专门应用在Megaupload网站的Greasemonkey脚本。如果你要亲自尝试一下,可以先看看这个演示。而这个脚本的作用,正如名字所示,可以识别这个网站的验证码。
 
现在,这个网站的验证码已经不是个什么难题了。(实际上,这是一个本来设计的就不怎么好的验证码,下面会给出一些例子)
对于这段脚本,我们有很多值得注意的事情:
  1. Canvas可以将图片嵌入到画布上,而getImageData函数可以从画布上获取验证码的像素数据。
  2. 这个脚本完全用JavaScript编写了一套神经网络的实现。
  3. 通过Canvas从图片获取的像素数据,被传入神经网络,通过OCR技术来获取图片中所表示的真实字符。
如果我们翻开源代码,就会发现这个脚本究竟是如何实现的,我们也可以领会这个验证码究竟是如何实现的。就像我之前提到的,这个验证码设计的本身就不好,只有3个字母,而且还用不同的颜色区分,只包含26个字母,最主要的,他们始终是同一字体。
 
第一个步骤很明确:把验证码的像素图像复制到Canvas中,并且转换为灰度模式。
function convert_grey(image_data){
for (var x = 0; x < image_data.width; x++){
for (var y = 0; y < image_data.height; y++){
var i = x*4+y*4*image_data.width;
var luma = Math.floor(image_data.data[i] * 299/1000 +
image_data.data[i+1] * 587/1000 +
image_data.data[i+2] * 114/1000); image_data.data[i] = luma;
image_data.data[i+1] = luma;
image_data.data[i+2] = luma;
image_data.data[i+3] = 255;
}
}
}

接下来Canvas被分解成3个独立的像素矩阵,每个矩阵都包含一个字母。(按道理来说,这是非常容易的事情。每个字母都由不同颜色组成,可以直接用颜色区分不同的字母。)

filter(image_data[0], 105);
filter(image_data[1], 120);
filter(image_data[2], 135);
function filter(image_data, colour){
for (var x = 0; x < image_data.width; x++){
for (var y = 0; y < image_data.height; y++){
var i = x*4+y*4*image_data.width; // Turn all the pixels of the certain colour to white
if (image_data.data[i] == colour) {
image_data.data[i] = 255;
image_data.data[i+1] = 255;
image_data.data[i+2] = 255; // Everything else to black
} else {
image_data.data[i] = 0;
image_data.data[i+1] = 0;
image_data.data[i+2] = 0;
}
}
}
}

然后最后,为了得到一个清晰的字母,我们还要把那些不相干的噪声像素从图片上去除。具体的方法,先要找到那些前面或者后面被黑色(之前没有匹配的像素)包裹的白色像素(之前已经匹配的像素),如果找到这样的像素,就简单的把它门直接删除。

var i = x*4+y*4*image_data.width;
var above = x*4+(y-1)*4*image_data.width;
var below = x*4+(y+1)*4*image_data.width; if (image_data.data[i] == 255 &&
image_data.data[above] == 0 &&
image_data.data[below] == 0) {
image_data.data[i] = 0;
image_data.data[i+1] = 0;
image_data.data[i+2] = 0;
}

我们现在已经得到了非常接近的图形,但还不够明确。脚本接下来会检测出这些形状的边缘,具体的是要找到图形中最上面、最下面、最左面和最右面的像素,然后把图形转换成矩形,最后将矩形的数据转换为一个20*25的矩阵。

cropped_canvas.getContext("2d").fillRect(0, 0, 20, 25);
var edges = find_edges(image_data[i]);
cropped_canvas.getContext("2d").drawImage(canvas, edges[0], edges[1],
edges[2]-edges[0], edges[3]-edges[1], 0, 0,
edges[2]-edges[0], edges[3]-edges[1]); image_data[i] = cropped_canvas.getContext("2d").getImageData(0, 0,
cropped_canvas.width, cropped_canvas.height);
最后,我们得到了什么?一个20*25的矩阵,里面包含着一个绘制着黑白两种颜色像素的矩形,真是令人兴奋啊。
 
矩形被进一步的缩小。一些关键位置的像素以接受体(receptors)的状态被提取出来,这些接受体最 终会被传入神经网络。举例而言,某个接受体具体对应的可能是位于9*6位置像素的状态,有像素或者没有像素。脚本会提取一系列这样的状态(远少于对 20*25矩阵整个计算的次数 - 只提取64种状态),并将这些状态传入神经网络。
 
你可能要问,为什么不直接对像素进行比较?为什么还要和神经网络扯在一起?问题的关键在于,我们要去掉那些模棱两可的情况。如果你试过了之前提到的演示就会发现,直接进行像素比较比通过神经网络比较,更容易出现偶尔判断错误的情况。但我们必须承认,对于大部分用户来说,直接的像素比较应该已经足够了。
 
下一个步骤就是尝试猜字母了。神经网络中传入了64个布尔值(由其中的一个字母图像获取而来),同时包含 一系列预先计算好的数据。神经网络的理念之一,就是我们首先要知道希望得到什么结果。很可能脚本的作者反复的运行脚本,并收集了一系列最佳评分,这些评分 可能包含这样的含义:“如果9*6位置存在像素,那么有58%的可能是字母A”。
 
当神经网络对验证码中一个字母对应的64个布尔值进行计算以后,和一个预先计算好的字母表相比较,然后为和每个字母的匹配都给出一个分数。(最后的结果可能类似:98%的可能是字母A,36%的可能是字母B等)
 
当对验证码中的三个字母都经过了计算以后,最终的结果也就出来了。确定的是,肯定不是100%精确的(不 知道如果在开始的时候不将字母转换成矩形,是不是可以提高评分的精度),但这已经相当好了,至少对于当前的用途来说。而且所有的操作都是在浏览器中,通过 基于标准的客户端技术实现的,这不是很神奇么?

补充说明一下,这个脚本应该算是一个特例吧,这项技术可能会应用在更多设计不良的验证码上,但对于更多设计复杂的验证码来说,就有点力不从心了(尤其是这种基于客户端的分析)。

我非常期待能有更多人从这个项目中得到灵感,开发出更多有意思的东西来,它的潜力太巨大了。

《译文》借助OCR和神经网络,用JavaScript识别验证码的更多相关文章

  1. 深度学习之卷积神经网络(CNN)的应用-验证码的生成与识别

    验证码的生成与识别 本文系作者原创,转载请注明出处:https://www.cnblogs.com/further-further-further/p/10755361.html 目录 1.验证码的制 ...

  2. 【原】Coursera—Andrew Ng机器学习—课程笔记 Lecture 18—Photo OCR 应用实例:图片文字识别

    Lecture 18—Photo OCR 应用实例:图片文字识别 18.1 问题描述和流程图 Problem Description and Pipeline 图像文字识别需要如下步骤: 1.文字侦测 ...

  3. javaScript识别网址文本并转为链接文本

    最近项目有个需求:用户之间发送消息时,如果发送者输入的信息中含有网址文本,要在接受者界面中显示网址链接,点击该链接直接跳转到网页.这个功能和 QQ 发送网址文本的效果非常像,可以说是一模一样的. 思路 ...

  4. 用标准3层神经网络实现MNIST识别

    一.MINIST数据集下载 1.https://pjreddie.com/projects/mnist-in-csv/      此网站提供了mnist_train.csv和mnist_test.cs ...

  5. ocr 文字区域检测及识别

    ocr 文字区域检测及识别 # coding=utf- from PIL import Image, ImageFilter, ImageEnhance from skimage.filters im ...

  6. 硕毕论文_基于 3D 卷积神经网络的行为识别算法研究

    论文标题:基于 3D 卷积神经网络的行为识别算法研究 来源/作者机构情况: 中  国  地  质  大  学(北京),计算机学院,图像处理方向 解决问题/主要思想贡献: 1. 使用张量CP分解的原理, ...

  7. 基于卷积神经网络的人脸识别项目_使用Tensorflow-gpu+dilib+sklearn

    https://www.cnblogs.com/31415926535x/p/11001669.html 基于卷积神经网络的人脸识别项目_使用Tensorflow-gpu+dilib+sklearn ...

  8. Pytorch实现基于卷积神经网络的面部表情识别(详细步骤)

    文章目录 一.项目背景 二.数据处理 1.标签与特征分离 2.数据可视化 3.训练集和测试集 三.模型搭建 四.模型训练 五.完整代码 一.项目背景数据集cnn_train.csv包含人类面部表情的图 ...

  9. selenium自动化 | 借助百度AI开放平台识别验证码登录职教云

    #通过借助百度AI开放平台识别验证码登录职教云 from PIL import Image from aip import AipOcr import unittest # driver.get(zj ...

随机推荐

  1. 中国象棋V2:Java源代码、毕业设计等所有文档,已经全部提交到CSDN-Code平台

    下载地址:https://code.csdn.net/FansUnion/chinesechess-v2 主要内容:Java源代码.毕业设计.API文档.声音图片等资源.Demo截图等一切的一切. 2 ...

  2. 【codeforces 785B】Anton and Classes

    [题目链接]:http://codeforces.com/contest/785/problem/B [题意] 给你两个时间各自能够在哪些时间段去完成; 让你选择两个时间段来完成这两件事情; 要求两段 ...

  3. cxf maven 依赖 No message body writer foud.. contenttype:application/json

    最近使用cxf发布rest服务时遇到了如题的异常,最后发现是缺少依赖的问题.ps:我并没有使用spring cxf基本运行需要如下依赖 1 <dependency> <groupId ...

  4. android studio的模拟器waiting for target device to come online原因

    android studio的模拟器一直waiting for target device to come online,demo也运行不上去 如图所示: 你很可能运行的android 6.0 (AP ...

  5. 利用WPF建立自己的3d gis软件(非axhost方式)(十二)SDK中的导航系统

    原文:利用WPF建立自己的3d gis软件(非axhost方式)(十二)SDK中的导航系统 先下载SDK:https://pan.baidu.com/s/1M9kBS6ouUwLfrt0zV0bPew ...

  6. ASP.NET中进度条的简单应用

    <html xmlns="http://www.w3.org/1999/xhtml" id="mainWindow"> <head> & ...

  7. win10 开机启动vmware并自动启动虚机

    思路 先实现程序或者命令启动VM并启动虚机,然后再开机启动这个程序. 1.实现一键启动VM和虚机 找了一圈的资料,有两个方法,都测试了,最终比较有效的是下面这个命令 "C:\Program ...

  8. 正交函数(orthogonal functions)

    a map is a function. 映射即函数: 1. 双线性映射与双线性形式 bilinear map 基于同一定义域,将两个向量空间(V,W)中的向量映射为第三个向量空间(X)的向量的函数: ...

  9. windows消息值全部定义,从消息值得到消息名称(系统消息定义从0到1023,从1024开始就是WM_USER,但是中间有325个WM_undefined消息,估计是备用,另外各控件都有一些reserved消息,也是为了备用)LostSpeed

    前言 在逆向算法扫描插件时, 遇到一个windows消息值在msdn中没有定义. 去查资料, 有个老外将全部windows消息值和消息名称定义都码好了:) 写个测试程序, 封装了一个接口, 从消息值得 ...

  10. 避免让WPF资源字典变得杂乱臃肿

    原文:避免让WPF资源字典变得杂乱臃肿   避免让WPF资源字典变得杂乱臃肿                            周银辉 今天看到项目种的一个XXXResource.xaml文件代码 ...