首先,不得不感谢一下ugg大大,我的所有成果都是在他的博文之下进一步完善的。
如有兴趣,请点击访问他的博客:
php实现验证码的识别(初级篇)
接下来,写我的思路:
1、将验证码按照字符个数,平均分开,比如,四位验证码则分为四张图片,其中一个字符占一张图片;
2、对每一张图片进行处理,先进行二值化处理,再接下去就将不包含有效字符的部分去除,仅保留包含字符的范围;
3、对这些处理过的图片进行建模,将特征码保存到数据库中;通过训练,建立对应的验证码特征库。
4、开始使用,对验证码做相对应的处理,取出字模,与特征库对比,取出最相近的字符即完成验证码的识别。
deal.php:
<?php
class deal {
public $img_path;
public $tmp;
public function __construct() {
$this->tmp = "temp";
}
function set($img) {
$this->img_path = $img;
}
function run($num = 4) {
$src = imagecreatefromjpeg ( $this->img_path );
if ($num != 1) {
$re = self::cut ( $src, $num );
foreach ( $re as $k => $v ) {
self::removeBlank ( $v,false );
}
return $re;
}else {
self::removeBlank ( $this->img_path,false );
}
}
/**
* 将图片水平切割
*
* @param unknown $img_src
* 图片源
* @param number $num
* 切割个数
* @return multitype:string
*/
function cut($img_src, $num) {
$size = getimagesize ( $this->img_path );
$height = $size [1];
$width = floor ( $size [0] / $num );
$result = array ();
if ($num == 1) {
return;
} else {
for($i = 0; $i < $num; $i ++) {
$tmp_name = "tmp_" . $i . ".jpg";
$img = imagecreatetruecolor ( $width, $height );
$res = imagecopy ( $img, $img_src, 0, 0, $i * $width, 0, $width, $height );
imagejpeg ( $img, $this->tmp . "/" . $tmp_name );
imagedestroy ( $img );
$result [$i] = $this->tmp . "/" . $tmp_name;
}
}
return $result;
}
/**
* 对图像黑白处理,并去除空白部分
*
* @param string $filename 图片路径
* @param bool $file 路径是否需要补齐到temp目录,false则直接使用$filename
*/
function removeBlank($filename,$file=true) {
if ($file) {
$res = imagecreatefromjpeg ( $this->tmp . "/" . $filename );
}else {
$filename=$filename;
}
$res = imagecreatefromjpeg ($filename);
$size = getimagesize ( $filename );
$white = imagecolorallocate ( $res, 255, 255, 255 );
$black = imagecolorallocate ( $res, 0, 0, 0 );
for($i = 0; $i < $size [1]; ++ $i) { // height
for($j = 0; $j < $size [0]; ++ $j) { // width
$rgb = imagecolorat ( $res, $j, $i );
$rgbarray = imagecolorsforindex ( $res, $rgb );
if ($rgbarray ['red'] < 150 || $rgbarray ['green'] < 150 || $rgbarray ['blue'] < 150) {
$data [$i] [$j] = 1;
imagesetpixel ( $res, $j, $i, $black );//深的颜色,全部显示为黑色
// echo "0";
} else {
$data [$i] [$j] = 0;
imagesetpixel ( $res, $j, $i, $white );//浅的颜色,全部显示为白色
// echo "-";
}
}
// echo "<br>";
}
//去噪
for($i = 0; $i < $size [1]; ++ $i) {
for($j = 0; $j < $size [0]; ++ $j) {
$num = 0;
if ($data [$i] [$j] == 1) {
// 上
if (isset ( $data [$i - 1] [$j] )) {
$num = $num + $data [$i - 1] [$j];
}
// 下
if (isset ( $data [$i + 1] [$j] )) {
$num = $num + $data [$i + 1] [$j];
}
// 左
if (isset ( $data [$i] [$j - 1] )) {
$num = $num + $data [$i] [$j - 1];
}
// 右
if (isset ( $data [$i] [$j + 1] )) {
$num = $num + $data [$i] [$j + 1];
}
// 上左
if (isset ( $data [$i - 1] [$j - 1] )) {
$num = $num + $data [$i - 1] [$j - 1];
}
// 上右
if (isset ( $data [$i - 1] [$j + 1] )) {
$num = $num + $data [$i - 1] [$j + 1];
}
// 下左
if (isset ( $data [$i + 1] [$j - 1] )) {
$num = $num + $data [$i + 1] [$j - 1];
}
// 下右
if (isset ( $data [$i + 1] [$j + 1] )) {
$num = $num + $data [$i + 1] [$j + 1];
}
}
if ($num < 1) {
$data [$i] [$j] = 0;
}
}
}
$x = 0;
$y = 0;
$x2 = $size [0];
$y2 = $size [1];
$flag = true;
foreach ( $data as $k => $v ) {//选择Y轴有效字符部分图像
if ($flag && ! in_array ( 1, $v )) {
$y = $k;
} else {
$flag = false;
if (in_array ( 1, $v )) {
$y2 = $k;
}
}
}
$data2 = self::fliparray ( $data );//开始去除X轴方向的空白部分
foreach ( $data2 as $k => $v ) {
if ($flag && ! in_array ( 1, $v )) {
$x = $k;
} else {
$flag = false;
if (in_array ( 1, $v )) {
$x2 = $k;
}
}
}
$height = $y2 - $y;
$width = $x2 - $x;
$img = imagecreatetruecolor ( $width, $height );//创建一个新图像,仅容纳字符
imagecopy ( $img, $res, 0, 0, $x, $y, $width, $height );//从源图像复制字符部分图像
imagejpeg ( $img, $filename );
}
/**
* 反转二维数组
*
* @param Array $arr
* @return Array
*/
protected function fliparray($arr) {
$newArr = array ();
foreach ( $arr as $k1 => $v1 ) {
foreach ( $v1 as $k2 => $v2 ) {
$newArr [$k2] [$k1] = $v2;
}
}
return $newArr;
}
}
Valid.php:
<?php
class Valid {
protected $ImagePath;
protected $DataArray;
protected $ImageSize;
protected $data;
protected $NumStringArray;
protected $db;
protected $keys;
public $result;
function __construct() {
$this->db = &load_class ( "Db" );
}
public function SetKeys() {
$sql = "select * from valid";
$this->keys = $this->db->select ( $sql );
}
public function setImage($Image) {
return $this->ImagePath = $Image;
}
public function getHec() {
$res = imagecreatefromjpeg ( $this->ImagePath );
$size = getimagesize ( $this->ImagePath );
$data = array ();
for($i = 0; $i < $size [1]; ++ $i) { // width
for($j = 0; $j < $size [0]; ++ $j) { // height
$rgb = imagecolorat ( $res, $j, $i );
$rgbarray = imagecolorsforindex ( $res, $rgb );
if ($rgbarray ['red'] < 125 || $rgbarray ['green'] < 125 || $rgbarray ['blue'] < 125) {
$data [$i] [$j] = 1;
// echo "0";
} else {
$data [$i] [$j] = 0;
// echo "-";
}
}
// echo "<br>";
}
for($i = 0; $i < $size [1]; ++ $i) {
for($j = 0; $j < $size [0]; ++ $j) {
$num = 0;
if ($data [$i] [$j] == 1) {
// 上
if (isset ( $data [$i - 1] [$j] )) {
$num = $num + $data [$i - 1] [$j];
}
// 下
if (isset ( $data [$i + 1] [$j] )) {
$num = $num + $data [$i + 1] [$j];
}
// 左
if (isset ( $data [$i] [$j - 1] )) {
$num = $num + $data [$i] [$j - 1];
}
// 右
if (isset ( $data [$i] [$j + 1] )) {
$num = $num + $data [$i] [$j + 1];
}
// 上左
if (isset ( $data [$i - 1] [$j - 1] )) {
$num = $num + $data [$i - 1] [$j - 1];
}
// 上右
if (isset ( $data [$i - 1] [$j + 1] )) {
$num = $num + $data [$i - 1] [$j + 1];
}
// 下左
if (isset ( $data [$i + 1] [$j - 1] )) {
$num = $num + $data [$i + 1] [$j - 1];
}
// 下右
if (isset ( $data [$i + 1] [$j + 1] )) {
$num = $num + $data [$i + 1] [$j + 1];
}
}
if ($num < 1) {
$data [$i] [$j] = 0;
}
}
}
$result = "";
$this->DataArray = $data;
foreach ( $this->DataArray as $k => $v ) {
foreach ( $v as $k2 => $v2 ) {
$result .= $v2;
}
}
$this->result = $result;
$this->ImageSize = $size;
}
public function run() {
self::SetKeys ();
$result = "";
$max = 0.0;
$num = 0;
if (is_array ( $this->keys )) {
foreach ( $this->keys as $k => $v ) {
$percent = 0.0;
similar_text ( $v ['numString'], $this->result, $percent );
if (intval ( $percent ) > $max) {
$max = $percent;
$num = $v ['code'];
if (intval ( $percent ) > 98)
break;
}
}
}
$result .= $num;
$this->data = $result;
return $result;
}
public function Draw() {
for($i = 0; $i < $this->ImageSize [1]; ++ $i) {
for($j = 0; $j < $this->ImageSize [0]; ++ $j) {
if ($this->DataArray [$i] [$j] == 1) {
echo "0";
} else {
echo "-";
}
}
echo "<br>";
}
}
public function clear() {
unset ( $this->DataArray );
unset ( $this->ImageSize );
unset ( $this->data );
}
}
?>