PHP生活

记录生活里的一分一秒

PHP生活

记录生活里的一分一秒

用PHP实现简单验证码的识别

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

发表回复

滚动到顶部