首先,不得不感谢一下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 ); } } ?>
用PHP实现简单验证码的识别