javascript验证码识别小记
关于javascript进行的简单的验证码识别
- 示例验证码:bilibili直播间领瓜子算式验证码(120px*40px)
经过分析,该验证码满足三个特征
- 长度固定,左边两个数字,然后一个符号,右边一个数字,总长度4位。
- 字符有限,0-9共10个数字,再加上一个加号和一个减号。
- 样式单一,没有字体变化,干扰元素极少,字符之间有一定的空隙。
在这篇博客中,它使用了提取各个数字的区块的识别方法,但是该方法只能应用在字符位置固定且等宽的情况,在bilibili这个验证码中,字符的初始位置并不固定,不能通过公式进行切割,字符的宽度也不相等,所以只能另外寻找方法
根据上面的规律和这次验证码的特殊性,可以确定出识别方案:
- 先通过二值化,将锯齿像素排除,将图片转为特定的二值化后的矩阵
- 依据空白,将字符分割开来
- 将分割开的字符分别确定其特征
分割开的字符,二值化后可以产生白色像素和黑色像素,在这里用1表示黑色像素,这样的话我们就可以成功表示出二值化后的像素矩阵
代码如下:
var ctx = $("#helper_canvas")[0].getContext("2d");
var pixels = ctx.getImageData(0,0,120,40).data;
//console.log(pixels);
var pix = []; //定义一维数组
var j = 0;
var i=0;
var n=0;
for(i=1;i<=40;i++)
{
pix[i] = []; //将每一个子元素又定义为数组
for(n=1;n<=120;n++)
{
let c = 1;
if(pixels[j]-(-pixels[j + 1])-(- pixels[j + 2]) >200){
c=0;
}
j = j+4;
pix[i][n]=c; //此时pix[i][n]可以看作是一个二级数组
}
}
//我们得到了二值化后的像素矩阵pix[40][120]
通过这个二值矩阵,我们将每一列求和,为0的位置就是该列全都是空白,因此可以求出一个和的数组lie[120],该数组记录了每一列上黑色像素的个数。
于是通过切割0的部分,我们可以将其各个字符的分割出来,并且去获得每一个字符的像素总数,第一列的像素数和最后一列的像素数。
代码如下:
var lie = [];
lie[0]=0;
for(i=1;i<=120;i++){
lie[i] = 0;
for(n=1;n<=40;n++){
lie[i] = lie[i]+pix[n][i];
}
}
var ta = [];
n=0;
for(i=1;i<=120;i++){
if(lie[i]>0&&lie[i-1]===0){
n++;
ta[n] = new Object();
ta[n].fi = lie[i];
ta[n].total = 0;
}
if(lie[i]>0){
ta[n].total = ta[n].total+lie[i];
}
if(lie[i-1]>0&&lie[i]===0){
ta[n].la = lie[i-1];
}
}
通过该代码,我们可以依据二值化矩阵得出每一个字符的三个属性,包括:像素个数,第一列像素个数,和最后一列像素个数
通过总像素个数,我们已经能够区分大部分的字符,但是0、6、9三个字符的像素个数接近,只能通过第一列像素个数和最后一列像素个数进行区分。
在对十几张验证码进行统计以后,我们可以大概得出如下的识别函数:
function get_word(a){
if(a.total<=50) return "-";
if(a.total>120&&a.total<135) return "+";
if(a.total>155&&a.total<162) return 1;
if(a.total>189&&a.total<195) return 7;
if(a.total>228&&a.total<237) return 4;
if(a.total>250&&a.total<260) return 2;
if(a.total>286&&a.total<296) return 3;
if(a.total>303&&a.total<313) return 5;
if(a.total>335&&a.total<342) return 8;
if(a.total>343&&a.total<350){
if(a.fi>24&&a.la>24) return 0;
if(a.fi<24&&a.la>24) return 9;
if(a.fi>24&&a.la<24) return 6;
}
}
通过该识别函数,即可得出四个字符,最后进行一下算式加减即可完成识别
最终效果:
本项目地址:bilibili自动领瓜子