PHP验证码识别实例
PHP验证码识别实例
PHP验证码识别实例,识别的过程包括对图像的二值化、降噪、补偿、切割、倾斜矫正、建库、匹配,最后会提供实例代码,能够直接运行识别。
简述

要识别的验证码相对比较简单,没有粘连字符,但是会有几种不同程度的字体加粗,以及大约0-30度的倾斜,还有字符的个数会在4-5个之间变化,相对来说还是使用Python进行验证码识别比较简单,如果有需要可以参考文章
强智教务系统验证码识别 OpenCV
强智教务系统验证码识别 Tensorflow CNN
二值化
图像都是由各个像素点组成,每个像素点可以量化成为rgb三种颜色值,根据验证码的颜色,调整三种颜色的阈值,将背景与字符过滤出来,背景置1,字符置0。
// 二值化
private static function binaryImage($image){
$img = [];
for($y = 0;$y < self::$width;$y++) {
for($x =0;$x < self::$height;$x++) {
if($y === 0 || $x === 0 || $y === self::$width - 1 || $x === self::$height - 1){
$img[$x][$y] = 1;
continue;
}
$rgb = imagecolorat($image, $y, $x);
$rgb = imagecolorsforindex($image, $rgb);
if($rgb['red'] < 255 && $rgb['green'] < 230 && $rgb['blue'] < 220) {
$img[$x][$y] = 0;
} else {
$img[$x][$y] = 1;
}
}
}
return $img;
}
1111111111111111111111111111011111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111
1111111111111111111111100000000011111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111
1111111111111111111111000000000111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111
1111111111111111111110000000000111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111
1111111111111111111110000000000111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111
1111111111111111111100000011111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111
1111111111111111111100000111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111
1111111111111111111100000111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111
1111111111111111111100100111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111
1111111111111111111100000111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111
1111111111111111111100000111111111111111111111111111111111111111111111111111111111111111111111111111111111111100111111111111111111111111111111111111111111111111000111111111111111111111111111111111111111111100000011111111111111111111111111111111111111
1111111111111111000000000000001111111111111111111111111111110000000011111111100000001111111111111111111111000000000000111111111111111111111111111111111111110000000000011111111111111111111111111111111111000000000000001111111111111111111111111111111111
1111111111111111100000100000001111111111111111111111111111110000000111111111000000001111111111111111111110000000000000001111111111111111111111111111111111100000000000000111111111111111111111111111111110000000000000000111111111111111111111111111111111
1111111111111111100000000000001111111111111111111111111111110000000111111111000000001111111111111111111100000000000000000111111111111111111111111111111110000000000000000011111111111111111111111111111100000000000000000001111111111111111111111111111111
1111111111111111100000000011101111111111111111111111111111110000100111111111000000011111111111111111111000000111110000000111111111111111111111111111111110000000000000000001111111111111111111111111111000000000000000000001111111111111111111111111111111
1111111111111111111100000111111111111111111111111111111111100000100111111111000000011111111111111111111000011111111100000111111111111111111111111111111100000000000000000000111111111111111111111111111000000000010000000000111111111111111111111111111111
1111111111111111111100000111111111111111111111111111111111100000101111111111000000011111111111111111110000011111111110000011111111111111111111111111111000000001111110000000111111111111111111111111110000000111111110000000111111111111111111111111111111
1111111111111111111100000111111111111111111111111111111111100000001111111111000000011111111111111111110000011111111110000011111111111111111111111111111001000011111110000000011111111111111111111111110000000111111110000000011111111111111111111111111111
1111111111111111111100000111111111111111111111111111111111100000001111111110000000011111111111111111110000011111111111111111111111111111111111111111110000000011111111000000011111111111111111111111110000000111111111001111111111111111111111111111111111
1111111111111111111100000111111111111111111111111111111111000000001111111110000000111111111111111111111000001111111111111111111111111111111111111111110000000111111111000000011111111111111111111111110000000000111111111111111111111111111111111111111111
1111111111111111111100000111111111111111111111111111111111000000011111111110000000111111111111111111111000000011111111111111111111111111111111111111110100000111111111100000001111111111111111111111111000000000001111111111111111111111111111111111111111
1111111111111111111100000111111111111111111111111111111111000000011111111110000000111111111111111111111000000000001111111111111111111111111111111111100000000001010111100000001111111111111111111111111000000000000000011111111111111111111111111111111111
1111111111111111111100000111111111111111111111111111111111000000011111111100000000111111111111111111111100000000000001111111111111111111111111111111100000000000000000000000001111111111111111111111111000000000000000000011111111111111111111111111111111
1111111111111111111100000111111111111111111111111111111111000000011111111100000001111111111111111111111110000000001000001111111111111111111111111111100000000000010110000011001111111111111111111111111100000000000000000000111111111111111111111111111111
1111111111111111111100000111111111111111111111111111111111000000011111111100000001111111111111111111111111100000000000000011111111111111111111111111100000000000000010000110001111111111111111111111111110000000000000110000111111111111111111111111111111
1111111111111111111100000111111111111111111111111111111110000000011111111100000001111111111111111111111111111100000000000011111111111111111111111111110000000000000000000000001111111111111111111111111111100000000000000000011111111111111111111111111111
1111111111111111111100000111111111111111111111111111111110000000111111111000000001111111111111111111111111111111110000000001111111111111111111111111110000000111111111111111111111111111111111111111111111111110000000000000011111111111111111111111111111
1111111111111111111100000111111111111111111111111111111110000000111111111000000001111111111111111111111111111111111110000001111111111111111111111111110000000111111111111111111111111111111111111111111111111111110000000000011111111111111111111111111111
1111111111111111111100000111111111111111111111111111111100000001111111111000000001111111111111111111111110111111111111000001111111111111111111111111110000000111111111011111111111111111111111111111111111101111111111000000001111111111111111111111111111
1111111111111111111100000111111111111111111111111111111100000001111111110000000011111111111111111111110000111111111111100001111111111111111111111111110000000011111111000001011111111111111111111111100000000111111111001000011111111111111111111111111111
1111111111111111111100000111111111111111111111111111111100000001111111100000000011111111111111111111110000011111111111100001111111111111111111111111111000000011111110000000011111111111111111111111100000000111111111001000011111111111111111111111111111
1111111111111111111100000111111111111111111111111111111100000000111111000000000011111111111111111111110000011111111111000001111111111111111111111111111000000001111110000000011111111111111111111111100000000011111111000100011111111111111111111111111111
1111111111111111111100000111111111111111111111111111111100000000001000000000000111111111111111111111111000001111111110000011111111111111111111111111111000000000000000000000111111111111111111111111110000000000000000000000111111111111111111111111111111
1111111111111111111100000111111111111111111111111111111110000000000000000000000111111111111111111111111000000001111100000011111111111111111111111111111100000100000000000000111111111111111111111111111000000000000000000000111111111111111111111111111111
1111111111111111111100000111111111111111111111111111111110000000000000011000100111111111111111111111111100000000000000000011111111111111111111111111111110000000000000000001111111111111111111111111111100000000000000000001111111111111111111111111111111
1111111111111111111100000111111111111111111111111111111111000000000000110000000111111111111111111111111110001000010000001111111111111111111111111111111111100000000000000011111111111111111111111111111110000000000000000011111111111111111111111111111111
1111111111111111111100000111111111111111111111111111111111100000000001110000000111111111111111111111111111000000000000011111111111111111111111111111111111110000000000001111111111111111111111111111111111000000000000001111111111111111111111111111111111
1111111111111111111111111111111111111111111111111111111111111000011111111111111111111111111111111111111111111100000111111111111111111111111111111111111111111111000011111111111111111111111111111111111111111110000111111111111111111111111111111111111111
1111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111
1111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111
降噪 补偿
验证码经常会加入一些噪点,这些噪点一般都是单独的点,有时候会加入几个单像素点连成干扰线,降噪的时候就需要去掉噪点与干扰线,我采用了将每个像素点周围四个像素点的值取出,计算如果周围四个像素点有两个以上是背景,也就是1的话,那么就认为这个是噪点,将其设为背景,也就是1。
当二值化的时候,不可避免的会将字符中一些小像素点过滤成了背景,此时就需要补偿这个字符,也是同样采用将周围四个字符进行统计,如果周围四个像素点有两个以上都是字符,也就是0,那么就认为这个像素点也是字符像素点,将其设为字符,也就是0。
// 降噪 补偿
private static function noiseReduce($img) {
$xCount = count($img[0]);
$yCount = count($img);
for ($i=1; $i < $yCount-1 ; $i++) {
for ($k=1; $k < $xCount-1; $k++) {
if($img[$i][$k] === 0){
$countOne = $img[$i][$k-1] + $img[$i][$k+1] + $img[$i+1][$k] + $img[$i-1][$k];
if($countOne > 2) $img[$i][$k] = 1;
}
if($img[$i][$k] === 1){
$countZero = $img[$i][$k-1] + $img[$i][$k+1] + $img[$i+1][$k] + $img[$i-1][$k];
if($countZero < 2) $img[$i][$k] = 0;
}
}
}
return $img;
}
1111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111
1111111111111111111111100000000111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111
1111111111111111111111000000000111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111
1111111111111111111110000000000111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111
1111111111111111111110000000000111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111
1111111111111111111100000011111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111
1111111111111111111100000111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111
1111111111111111111100000111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111
1111111111111111111100000111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111
1111111111111111111100000111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111
1111111111111111111100000111111111111111111111111111111111111111111111111111111111111111111111111111111111111100111111111111111111111111111111111111111111111111000111111111111111111111111111111111111111111100000011111111111111111111111111111111111111
1111111111111111100000000000001111111111111111111111111111110000000111111111100000001111111111111111111111000000000000111111111111111111111111111111111111110000000000011111111111111111111111111111111111000000000000001111111111111111111111111111111111
1111111111111111100000000000001111111111111111111111111111110000000111111111000000001111111111111111111110000000000000001111111111111111111111111111111111100000000000000111111111111111111111111111111110000000000000000111111111111111111111111111111111
1111111111111111100000000000001111111111111111111111111111110000000111111111000000001111111111111111111100000000000000000111111111111111111111111111111110000000000000000011111111111111111111111111111100000000000000000001111111111111111111111111111111
1111111111111111100000000011111111111111111111111111111111110000000111111111000000011111111111111111111000000111110000000111111111111111111111111111111110000000000000000001111111111111111111111111111000000000000000000001111111111111111111111111111111
1111111111111111111100000111111111111111111111111111111111100000000111111111000000011111111111111111111000011111111100000111111111111111111111111111111100000000000000000000111111111111111111111111111000000000000000000000111111111111111111111111111111
1111111111111111111100000111111111111111111111111111111111100000001111111111000000011111111111111111110000011111111110000011111111111111111111111111111000000001111110000000111111111111111111111111110000000111111110000000111111111111111111111111111111
1111111111111111111100000111111111111111111111111111111111100000001111111111000000011111111111111111110000011111111110000011111111111111111111111111111000000011111110000000011111111111111111111111110000000111111110000000111111111111111111111111111111
1111111111111111111100000111111111111111111111111111111111100000001111111110000000011111111111111111110000011111111111111111111111111111111111111111110000000011111111000000011111111111111111111111110000000111111111001111111111111111111111111111111111
1111111111111111111100000111111111111111111111111111111111000000001111111110000000111111111111111111111000001111111111111111111111111111111111111111110000000111111111000000011111111111111111111111110000000000111111111111111111111111111111111111111111
1111111111111111111100000111111111111111111111111111111111000000011111111110000000111111111111111111111000000011111111111111111111111111111111111111110000000111111111100000001111111111111111111111111000000000001111111111111111111111111111111111111111
1111111111111111111100000111111111111111111111111111111111000000011111111110000000111111111111111111111000000000001111111111111111111111111111111111100000000000000111100000001111111111111111111111111000000000000000011111111111111111111111111111111111
1111111111111111111100000111111111111111111111111111111111000000011111111100000000111111111111111111111100000000000001111111111111111111111111111111100000000000000000000000001111111111111111111111111000000000000000000011111111111111111111111111111111
1111111111111111111100000111111111111111111111111111111111000000011111111100000001111111111111111111111110000000000000001111111111111111111111111111100000000000000000000010001111111111111111111111111100000000000000000000111111111111111111111111111111
1111111111111111111100000111111111111111111111111111111111000000011111111100000001111111111111111111111111100000000000000011111111111111111111111111100000000000000000000000001111111111111111111111111110000000000000000000111111111111111111111111111111
1111111111111111111100000111111111111111111111111111111110000000011111111100000001111111111111111111111111111100000000000011111111111111111111111111110000000000000000000000001111111111111111111111111111100000000000000000011111111111111111111111111111
1111111111111111111100000111111111111111111111111111111110000000111111111000000001111111111111111111111111111111110000000001111111111111111111111111110000000111111111111111111111111111111111111111111111111110000000000000011111111111111111111111111111
1111111111111111111100000111111111111111111111111111111110000000111111111000000001111111111111111111111111111111111110000001111111111111111111111111110000000111111111111111111111111111111111111111111111111111110000000000011111111111111111111111111111
1111111111111111111100000111111111111111111111111111111100000001111111111000000001111111111111111111111111111111111111000001111111111111111111111111110000000111111111111111111111111111111111111111111111111111111111000000011111111111111111111111111111
1111111111111111111100000111111111111111111111111111111100000001111111110000000011111111111111111111110000111111111111100001111111111111111111111111110000000011111111000000011111111111111111111111100000000111111111000000011111111111111111111111111111
1111111111111111111100000111111111111111111111111111111100000001111111100000000011111111111111111111110000011111111111100001111111111111111111111111111000000011111110000000011111111111111111111111100000000111111111000000011111111111111111111111111111
1111111111111111111100000111111111111111111111111111111100000000111111000000000011111111111111111111110000011111111111000001111111111111111111111111111000000001111110000000011111111111111111111111100000000011111111000000011111111111111111111111111111
1111111111111111111100000111111111111111111111111111111100000000000000000000000111111111111111111111111000001111111110000011111111111111111111111111111000000000000000000000111111111111111111111111110000000000000000000000111111111111111111111111111111
1111111111111111111100000111111111111111111111111111111110000000000000000000000111111111111111111111111000000001111100000011111111111111111111111111111100000000000000000000111111111111111111111111111000000000000000000000111111111111111111111111111111
1111111111111111111100000111111111111111111111111111111110000000000000010000000111111111111111111111111100000000000000000011111111111111111111111111111110000000000000000001111111111111111111111111111100000000000000000001111111111111111111111111111111
1111111111111111111100000111111111111111111111111111111111000000000000110000000111111111111111111111111110000000000000001111111111111111111111111111111111100000000000000011111111111111111111111111111110000000000000000011111111111111111111111111111111
1111111111111111111100000111111111111111111111111111111111100000000001110000000111111111111111111111111111000000000000011111111111111111111111111111111111110000000000001111111111111111111111111111111111000000000000001111111111111111111111111111111111
1111111111111111111111111111111111111111111111111111111111111000011111111111111111111111111111111111111111111100000111111111111111111111111111111111111111111111000011111111111111111111111111111111111111111110000111111111111111111111111111111111111111
1111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111
1111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111
切割
由于此验证码并没有粘连,对于字符的切割相对而言比较简单,纵向统计出切割字符的起始与终止位置,切割后分别置入数组中,然后将横向的空白去除,同样也是统计字符有0值的起始行与终止行,再做切割,仅保留字符。
// 裁剪
private static function cutImg($img){
$xCount = count($img[0]);
$yCount = count($img);
$xFilter = [];
for($x = 0;$x < $xCount;$x++) {
$filter = true;
for($y = 0;$y < $yCount;$y++) $filter = $filter && ($img[$y][$x] === 1);
if($filter) $xFilter[] = $x;
}
$xImage = array_values(array_diff(range(0, $xCount-1), $xFilter));
$wordImage = [];
$preX = $xImage[0] - 1;
$wordCount = 0;
foreach($xImage as $xKey => $x) {
if($x != ($preX + 1)) $wordCount++;
$preX = $x;
for($y = 0;$y < $yCount;$y++) $wordImage[$wordCount][$y][] = $img[$y][$x];
}
$cutImg = [];
foreach($wordImage as $i => $image) {
$xCount = count($image[0]);
$yCount = count($image);
$start = 0;
for ($j=0; $j < $yCount; ++$j) {
$stopFlag = false;
for ($k=0; $k < $xCount; ++$k) {
if ($image[$j][$k] === 0) {
$start = $j;
$stopFlag = true;
break;
}
}
if($stopFlag) break;
}
$stop = $yCount-1;
for ($j=$yCount-1; $j >= 0; --$j) {
$stopFlag = false;
for ($k=0; $k < $xCount; ++$k) {
if ($image[$j][$k] === 0) {
$stop = $j;
$stopFlag = true;
break;
}
}
if($stopFlag) break;
}
for ($k=$start; $k <= $stop ; ++$k) {
$cutImg[$i][] = $image[$k];
}
// self::showImg($cutImg[$i]);
$cutImg[$i] = self::adjustImg($cutImg[$i]);
// self::showImg($cutImg[$i]);
}
return $cutImg;
}
1111111111111000001111111
1111111100000000000001111
1111111000000000000000011
1111110000000000000000011
1111100000000000000000001
1111000000001111000000001
1110000000011111100000000
1110000000111111110000000
1111111111111111110000000
1111111111111111110000000
1111111111111111100000001
1111111100000000000000001
1111100000000000000000001
1110000000000000000000001
1100000000000000000000001
1000000000000111100000011
1000000001111111000000011
1000000011111111000000011
0000000111111111000000011
0000000111111110000000111
0000000111111100000000111
0000000011111000000000111
1000000001100000000000111
1000000000000000000000111
1000000000000000000000111
1100000000000010000000111
1111000000001110000000111
1111100001111111111111111
倾斜矫正
对于倾斜矫正我尝试了两种方案,一个是使用线性回归,另一个是使用投影法。
线性回归
使用线性回归,取得每一行上字符像素点的中点的坐标,使用最小二乘法拟合曲线,得到一个斜率,也就相当于得到了这个字符的倾斜角度,然后根据斜率来矫正这个字符的倾斜度,这个方式对于n这样的字符效果比较不错,但是对于j这样的字符效果就比较差。
$img = [
[1,1,1,1,1,0,0,0,0,1,1,1,1,0,0,0,0,0,0,0,0,0,1,1],
[1,1,1,1,1,0,0,0,0,1,1,1,0,0,0,0,0,0,0,0,0,0,0,1],
[1,1,1,1,0,0,0,0,1,1,1,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,1,1,1,1,0,0,0,0,0],
[1,1,1,1,0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,0,0,0,0],
[1,1,1,1,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,1,0,0,0,0],
[1,1,1,1,0,0,0,0,0,0,1,1,1,1,1,1,1,1,1,1,0,0,0,0],
[1,1,1,0,0,0,0,0,0,1,1,1,1,1,1,1,1,1,1,1,0,0,0,0],
[1,1,1,0,0,0,0,0,0,1,1,1,1,1,1,1,1,1,1,1,0,0,0,0],
[1,1,1,0,0,0,0,0,1,1,1,1,1,1,1,1,1,1,1,1,0,0,0,0],
[1,1,1,0,0,0,0,0,1,1,1,1,1,1,1,1,1,1,1,0,0,0,0,0],
[1,1,1,0,0,0,0,1,1,1,1,1,1,1,1,1,1,1,1,0,0,0,0,0],
[1,1,0,0,0,0,0,1,1,1,1,1,1,1,1,1,1,1,1,0,0,0,0,1],
[1,1,0,0,0,0,0,1,1,1,1,1,1,1,1,1,1,1,0,0,0,0,0,1],
[1,1,0,0,0,0,1,1,1,1,1,1,1,1,1,1,1,1,0,0,0,0,0,1],
[1,1,0,0,0,0,1,1,1,1,1,1,1,1,1,1,1,1,0,0,0,0,0,1],
[1,1,0,0,0,0,1,1,1,1,1,1,1,1,1,1,1,1,0,0,0,0,0,1],
[1,0,0,0,0,0,1,1,1,1,1,1,1,1,1,1,1,1,0,0,0,0,1,1],
[1,0,0,0,0,0,1,1,1,1,1,1,1,1,1,1,1,1,0,0,0,0,1,1],
[1,0,0,0,0,0,1,1,1,1,1,1,1,1,1,1,1,0,0,0,0,0,1,1],
[1,0,0,0,0,1,1,1,1,1,1,1,1,1,1,1,1,0,0,0,0,0,1,1],
[1,0,0,0,0,1,1,1,1,1,1,1,1,1,1,1,1,0,0,0,0,0,1,1],
[0,0,0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,0,0,0,0,1,1,1],
[0,0,0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,0,0,0,0,1,1,1],
[0,0,0,0,1,1,1,1,1,1,1,1,1,1,1,1,0,0,0,0,0,1,1,1],
[0,0,0,0,1,1,1,1,1,1,1,1,1,1,1,1,0,0,0,0,0,1,1,1],
];
ImgIdenfy::showImg($img);
$mixX = 0.0;
$mixY = 0.0;
$mixXX = 0.0;
$mixXY = 0.0;
$yCount = count($img);
$xCount = count($img[0]);
foreach($img as $i => $line) {
$x = 0;
$xValidCount = 0;
foreach($line as $k => $unit) {
if($unit === 0) {
$x += $k;
++$xValidCount;
}
}
if($xValidCount) {
$pointX = $x/$xValidCount;
$pointY = $yCount - $i;
$mixX += $pointX;
$mixY += $pointY;
$mixXX += ($pointX*$pointX);
$mixXY += ($pointX*$pointY);
}
}
$linearK = -($mixXY - $mixX*$mixY/$yCount) / ($mixXX - $mixX*$mixX/$yCount);
// if($linearK > -1 && $linearK < 1) return $img;
$whirlImg = [];
foreach($img as $i => $line) {
$pointY = $i;
if(!isset($whirlImg[$pointY])) $whirlImg[$pointY]=[];
foreach($line as $pointX => $unit) {
if(!isset($whirlImg[$pointY][$pointX])) $whirlImg[$pointY][$pointX]=1;
// $newY = (int)($pointY*sqrt(1+$linearK*$linearK)/$linearK);
$newY = (int)($pointY);
$newX = (int)($pointX-$pointY/$linearK);
if($newX >= 0 && $newX < $xCount && $newY >= 0 && $newY < $yCount) $whirlImg[$newY][$newX] = $unit;
}
}
$finishedImg = [];
for ($i=0; $i < $xCount; ++$i) {
for($k=0; $k < $yCount; ++$k) {
if($whirlImg[$k][$i] !== 1){
for($y = 0;$y < $yCount;++$y) $finishedImg[$y][] = $whirlImg[$y][$i];
break;
}
}
}
ImgIdenfy::showImg($finishedImg);
111110000111100000000011
111110000111000000000001
111100001110000000000000
111100000000000111100000
111100000000111111110000
111100000001111111110000
111100000011111111110000
111000000111111111110000
111000000111111111110000
111000001111111111110000
111000001111111111100000
111000011111111111100000
110000011111111111100001
110000011111111111000001
110000111111111111000001
110000111111111111000001
110000111111111111000001
100000111111111111000011
100000111111111111000011
100000111111111110000011
100001111111111110000011
100001111111111110000011
000011111111111110000111
000011111111111110000111
000011111111111100000111
000011111111111100000111
10000111100000000011
10000111000000000001
00001110000000000000
00000000000111100000
00000000111111110000
10000000111111111000
10000001111111111000
00000011111111111000
00000011111111111000
00000111111111111000
10000011111111111000
10000111111111111000
00000111111111111000
00000111111111110000
00001111111111110000
10000111111111111000
10000111111111111000
00000111111111111000
00000111111111111000
00000111111111110000
10000111111111111000
10000111111111111000
00001111111111111000
00001111111111111000
00001111111111110000
10000111111111111000
投影法
由于直接线性拟合的方式对于一些字符的效果比较差,于是采用投影法的方式,字符如果进行旋转,那么他的宽度势必会增加,于是可以在一定范围内尝试旋转字符,取得旋转过程中宽度最小时的字符,就是矫正后的字符。由于直接将竖直的字符根据斜率旋转的话,因为tan90°不存在,不好界定逆时针旋转的范围,于是首先将字符数组进行转置,然后就可以在斜率-0.5-0.5的范围内顺时针旋转,然后再将其转置回即可,我在实现的过程中有比较多的重复运算,这个主要是需要数学推算,而我是一步步实现的计算,还有就是旋转的过程中如果字符宽度由小到大变化的时候就可以逆向运算或者停止运算了,就像一个梯度下降的方式,此外我并没有使用矩阵方式的运算,如果使用矩阵的话实现会比较简单,PHP中有PHP-ML这样的机器学习库,其中就有矩阵运算方面的方法,当然也可以直接使用PHP-ML进行神经网络的训练。
// 旋转
private static function whirl($img, $yCount, $xCount, $linearK){
$whirlImg = [];
foreach($img as $i => $line) {
$pointY = $yCount - $i - 1;
if(!isset($whirlImg[$pointY])) $whirlImg[$pointY]=[];
foreach($line as $pointX => $unit) {
if(!isset($whirlImg[$pointY][$pointX])) $whirlImg[$pointY][$pointX]=1;
$newY = (int)($pointY - $pointX*$linearK);
$newX = (int)($pointX);
if($unit === 0 && ($newY < 0 || $newY >= $yCount)) return [$yCount+1, $img];
if($newX >= 0 && $newX < $xCount && $newY >= 0 && $newY < $yCount) $whirlImg[$newY][$newX] = $unit;
}
}
$cutImg = [];
$height = $yCount;
foreach ($whirlImg as $j => $line) {
foreach ($line as $k => $v) {
if($v !== 1) {
--$height;
break;
}
}
}
return [$yCount - $height, $whirlImg];
}
// 倾斜调整
private static function adjustImg($img){
$reverseImg = [];
$yCount = count($img);
$xCount = count($img[0]);
for ($i=0; $i < $yCount; ++$i) {
$pointY = $yCount - $i - 1;
for($k=0; $k < $xCount; ++$k) {
$reverseImg[$k][$i] = $img[$pointY][$k];
}
}
list($yCount,$xCount) = [$xCount,$yCount];
$min = $yCount;
$minImg = $reverseImg;
for ($k= -0.5 ; $k <= 0.5; $k = $k + 0.05) {
list($tempMin, $tempMinImg) = self::whirl($reverseImg, $yCount, $xCount, $k);
if($tempMin < $min) {
$min = $tempMin;
$minImg = $tempMinImg;
}
}
$removedImg = [];
foreach ($minImg as $j => $line) {
foreach ($line as $k => $v) {
if($v !== 1) {
$removedImg[] = $line;
break;
}
}
}
$reverseImg = [];
$xCount = count($removedImg[0]);
$yCount = count($removedImg);
$reverseImg = [];
for ($i=0; $i < $xCount; ++$i) {
for($k=0; $k < $yCount; ++$k) {
$pointX = $xCount - $i - 1;
$reverseImg[$i][$k] = $removedImg[$k][$pointX];
}
}
return $reverseImg;
}
1111111111111000001111111
1111111100000000000001111
1111111000000000000000011
1111110000000000000000011
1111100000000000000000001
1111000000001111000000001
1110000000011111100000000
1110000000111111110000000
1111111111111111110000000
1111111111111111110000000
1111111111111111100000001
1111111100000000000000001
1111100000000000000000001
1110000000000000000000001
1100000000000000000000001
1000000000000111100000011
1000000001111111000000011
1000000011111111000000011
0000000111111111000000011
0000000111111110000000111
0000000111111100000000111
0000000011111000000000111
1000000001100000000000111
1000000000000000000000111
1000000000000000000000111
1100000000000010000000111
1111000000001110000000111
1111100001111111111111111
111111111110000011111111
111111000000000000011111
111110000000000000000111
111100000000000000000111
111000000000000000000011
110000000011110000000011
100000000111111000000001
100000001111111100000001
111111111111111110000000
111111111111111110000000
111111111111111100000001
111111100000000000000001
111100000000000000000001
110000000000000000000001
100000000000000000000001
000000000000111100000011
000000001111111000000011
000000011111111000000011
000000011111111100000001
000000011111111000000011
000000011111110000000011
000000001111100000000011
100000000110000000000011
100000000000000000000011
100000000000000000000011
110000000000001000000011
111100000000111000000011
111110000111111111111111
建库
将验证码矫正过后,就需要建立特征匹配库了,这里我直接使用了将二值化的数组转化为字符串全部作为特征写入一个特征匹配数组,再手动打码,若是识别出的字符与我手动打码的字符不符,就将其加入特征匹配数组,然后将字符数组序列化存储到文件中,然后将这个序列化后的字符串进行压缩,存储到文件中,我提取的特征数组有150个字符特征码,占用约8KB,注意我这是将PHP作为脚本使用的,配置好环境变量写入空数据后再使用php Build.php即可开始提取特征码。
// 写入空序列化数组
// $info = serialize([]);
// $library = fopen("library", "w+");
// fwrite($library,gzcompress($info));
// fclose($library);
$library = fopen("library", "r+");
$info = fread($library,filesize("library"));
if(!$info) $charMap = [];
else $charMap = unserialize(gzuncompress($info));
while (1) {
$img = imagecreatefromjpeg("http://grdms.sdust.edu.cn:8081/security/jcaptcha.jpg"); //获取图片
imagejpeg($img,"v.jpg"); // 写入硬盘
list($result, $imgStringArr) = ImgIdenfy::build($img, $charMap, 250, 100);
echo($result."\n");
$input = fgets(STDIN);
if(isset($input[0]) && $input[0] === "$") break;
$n = strlen($input) - 2;
for ($i=0; $i < $n; $i++) {
if(!isset($result[$i]) || $input[$i] !== $result[$i]) $charMap[$input[$i].mt_rand(1, 10000)] = $imgStringArr[$i];
}
echo count($charMap)."\n";
ftruncate($library,0);
rewind($library);
fwrite($library,gzcompress(serialize($charMap)));
}
fclose($library);
匹配
由于是直接将全部的特征信息存入文件,直接使用循环对比字符串的值即可,为了提高准确率,我将两个对比字符串的第一个0进行对齐,然后再进行遍历,取得相同字符的数量,此外由于对比的字符串的长度不同,将字符串的长度信息乘以一定权值也作为一部分信息计入相似度中,当然PHP中提供了similar_text函数进行字符串相似度对比,使用此函数的话识别率会提升,但是由于字符串长度过长,对比匹配的时间比较慢,权衡时间消耗与正确率还是选择了自行匹配的方式。
// 对比
private static function comparedText($s1,$s2){
$s1N = strlen($s1);
$s2N = strlen($s2);
$i = -1;
$k = -1;
$percent = -abs($s1N - $s2N) * 0.1;
while(++$i<$s1N && $s1[$i]) {}
while(++$k<$s2N && $s2[$k]) {}
while ($i<$s1N && $k<$s2N) ($s1[$i++] === $s2[$k++]) ? $percent++ : "";
return $percent;
// $percent = 0;
// $N = $s1N < $s2N ? $s1N : $s2N;
// for ($i=0; $i < $N; ++$i) {
// ($s1[$i] === $s2[$i]) ? $percent++ : "";
// }
// return $percent;
}
// 匹配
private static function matchCode($imgGroup,$charMap){
$record = "";
$imgStringArr = [];
foreach ($imgGroup as $img) {
$maxMatch = 0;
$tempRecord = "";
$s = ImgIdenfy::getString($img);
foreach ($charMap as $key => $value) {
// similar_text(ImgIdenfy::getString($img),$value,$percent);
$percent = self::comparedText($s , $value);
if($percent > $maxMatch){
$maxMatch = $percent;
$tempRecord = $key[0];
}
}
$record = $record.$tempRecord;
$imgStringArr[] = $s;
}
return [$record, $imgStringArr];
}
实例代码
如果觉得不错,点个star吧
https://github.com/WindrunnerMax/Example
PHP验证码识别实例的更多相关文章
- Python验证码识别处理实例(转载)
版权声明:本文为博主林炳文Evankaka原创文章,转载请注明出处http://blog.csdn.net/evankaka 一.准备工作与代码实例 1.PIL.pytesser.tesseract ...
- Python验证码识别处理实例(转)
一.准备工作与代码实例 1.PIL.pytesser.tesseract (1)安装PIL:下载地址:http://www.pythonware.com/products/pil/(CSDN下载) 下 ...
- Python3 简单验证码识别思路及实例
1.介绍 在爬虫中经常会遇到验证码识别的问题,现在的验证码大多分计算验证码.滑块验证码.识图验证码.语音验证码等四种.本文就是识图验证码,识别的是简单的验证码,要想让识别率更高, 识别的更加准确就需要 ...
- 【转】Python验证码识别处理实例
原文出处: 林炳文(@林炳文Evankaka) 一.准备工作与代码实例 1.PIL.pytesser.tesseract (1)安装PIL:下载地址:http://www.pythonware.com ...
- Python验证码识别处理实例
一.准备工作与代码实例 1.PIL.pytesser.tesseract (1)安装PIL:下载地址:http://www.pythonware.com/products/pil/(CSDN下载) 下 ...
- python验证码识别
关于利用python进行验证码识别的一些想法 用python加“验证码”为关键词在baidu里搜一下,可以找到很多关于验证码识别的文章.我大体看了一下,主要方法有几类:一类是通过对图片进行处 理,然后 ...
- 使用python及工具包进行简单的验证码识别
相信大家利用 Python 写的爬虫应该遇到过要输入验证码的尴尬局面,又或者写了个自动填充表单的小程序,结果就卡在了验证码上. 在ctf中有⼀一些题⽬目,本身有弱验证码识别绕过,那么我们怎么解决呢? ...
- 利用jTessBoxEditor工具进行Tesseract3.02.02样本训练,提高验证码识别率
1.背景 前文已经简要介绍tesseract ocr引擎的安装及基本使用,其中提到使用-l eng参数来限定语言库,可以提高识别准确率及识别效率. 本文将针对某个网站的验证码进行样本训练,形成自己的语 ...
- 关于利用python进行验证码识别的一些想法
转载:@小五义http://www.cnblogs.com/xiaowuyi 用python加“验证码”为关键词在baidu里搜一下,可以找到很多关于验证码识别的文章.我大体看了一下,主要方法有几类: ...
- 字符型图片验证码识别完整过程及Python实现
字符型图片验证码识别完整过程及Python实现 1 摘要 验证码是目前互联网上非常常见也是非常重要的一个事物,充当着很多系统的 防火墙 功能,但是随时OCR技术的发展,验证码暴露出来的安全问题也越 ...
随机推荐
- java - 冒泡排序求最值
public class Bubble3 { public static void main(String[] args) { int[] arr; arr = new int[]{2,3,6,1}; ...
- [转帖]Always-on Profiling for Production Systems
https://0x.tools/ 0x.tools (GitHub) is a set of open-source utilities for analyzing application perf ...
- [转帖]FIO – IO压力测试工具
https://blog.csdn.net/younger_china/article/details/71129541 <存储工具系列文章>主要介绍存储相关的测试和调试工具,包括不限于d ...
- 【转帖】mysql一个索引块有多少指针_深刻理解MySQL系列之索引
索引 查找一条数据的过程 先看下InnoDB的逻辑存储结构:node 表空间:能够看作是InnoDB存储引擎逻辑结构的最高层,全部的数据都存放在表空间中.默认有个共享表空间ibdata1.若是启用in ...
- 【转帖】JVM的发展历程
目录 1.Sun Classic VM 2.Exact VM 3.Sun HotSpot(主流) 4.JRockit 5.IBM J9 6.下一代虚拟机Graal VM 1.Sun Classic V ...
- [转帖]服务器稳定性测试-LTP压力测试方法及工具下载
简介 LTP(LinuxTest Project)是SGI.IBM.OSDL和Bull合作的项目,目的是为开源社区提供一个测试套件,用来验证Linux系统可靠性.健壮性和稳定性.LTP测试套件是测试L ...
- [转帖]iptables 执行清除命令 iptables -F 要非常小心的
使用 /sbin/iptables -F 要小心,搞不好,你就马上同服务器断开连接了 以下是来自 http://wiki.ubuntu.org.cn/IptablesHowTo 上的说明 可以通过/s ...
- BMC修改密码
公司里的服务器都托管出去了, 为了好维护, 都给自己的机器设置了BMC远程管理的端口, 安全起见自己修改了密码. 方法很简单.默认用户密码是 用户:root 密码: root 用户:admin 密码: ...
- 浅谈基于Web的跨平台桌面应用开发
作者:京东物流 王泽知 近些年来,跨平台跨端一直是比较热门的话题,Write once, run anywhere,一直是我们开发者所期望的,跨平台方案的优势十分明显,对于开发者而言,可以做到一次开发 ...
- pymongo中针对指定集合更新validator规则
问题描述: 针对mongo中已创建的集合,更新validator验证器规则 解决方法 在确保pymongo中所使用的用户对目标数据库具有dbAdmin之类的管理权限的前提下(若无权限,可在mongo中 ...