首页  >  文章  >  后端开发  >  PHP读取图片数据原理与实现

PHP读取图片数据原理与实现

WBOY
WBOY原创
2016-06-23 14:19:001547浏览

本帖最后由 hudie631489527 于 2012-07-21 23:34:34 编辑

好久没有写文章了,手也开始痒痒了

这次为大家带来的是一个关于PHP提取图片数据的内容

这里没有什么新技术,只是为了让大家了解PHP也可以处理图片以及处理的原理和方式

在此实现一个简单的DEMO,读取图片中指定位置的数据‘特定字母+数字’(本例图片来源于cacti监控流量图片)


以下两步分开单进行

I 先来取模操作,实现步骤:
1.定位图片需要识别区域,从图片中取出此部分
2.将此部分的字模提取出来,记录到字模文件中,供以后匹配使用(为了得到完整的字模,所以需要多张图片进行测试)


II进行图片文字提取,实现步骤:

1.定位图片需要识别区域,从图片中取出此部分

2.将此部分的字模提取出来,与已经保存好的字模文件中数据对比,找出此字模对应的数据即可


这两步分开说,个人觉得是很有必要的,虽然他们有很多相似之处,但毕竟两者是两个不同的过程

刚洗个澡想了一下,还是觉得先介绍第二部分,然后在介绍第一部分,这样大家可能会有兴趣点,先看到结果,勾起你们的欲望,哈哈哈…


正式进入主题:

先将需要操作的类放出来,点击下面右边箭头可查看类文件
<?php/*** * @author: Buty(孟婆) *  */class picWords {	private $width;	private $height;	private $zimo_file = 'piczimo.php'; //需要生成的字模文件	private $zimo_info = '';	private $continued; //高峰流量持续的时间	private $warnning_data; //流量报警峰值	private $hourstep; //一小时在时间轴上的长度	function __construct() {		if(!extension_loaded('gd')) { //需要gd扩展的支持			exit('GD extension is supported,please load GD extension and go on.');		}		if(file_exists('config.php')) {			require 'config.php';			$this->continued = $continued;			$this->warnning_data = $warnning_data;			$this->hourstep = $hourstep;		}			}/*****************************************自行创建字模图片与字模数组文件********************************/		function readPicDot($picfile) {		$res = imagecreatefrompng($picfile);		$size = getimagesize($picfile);		$this->width = $size[0];		$this->height = $size[1];		$data = array();				for($j = 0; $j < $this->height; ++$j) {			/*			 * 取需要的数据段 			 * 262,273 day.png			 */						if($j > 262 && $j < 273) {   				for($i=0; $i < $this->width; ++$i) {					if($i > 420) {						$rgb = imagecolorat($res,$i,$j);						$rgbarray = imagecolorsforindex($res, $rgb);						if($rgbarray['red'] < 145 && $rgbarray['green'] < 145 & $rgbarray['blue'] < 145) {							$data[$i][$j]=1;						} else {							$data[$i][$j]=0;						}					}				}							}		}				return $data;	}	function readMaxOutDot($picfile) {		$res = imagecreatefrompng($picfile);		$size = getimagesize($picfile);		$this->width = $size[0];		$this->height = $size[1];		$data = array();				for($j = 0; $j < $this->height; ++$j) {			/*			 * 取需要的数据段 			 * 262,273 day.png			 */						if($j > 262 && $j < 273) {   				for($i=0; $i < $this->width; ++$i) {					if($i < 180 && $i > 90) {						$rgb = imagecolorat($res,$i,$j);						$rgbarray = imagecolorsforindex($res, $rgb);						if($rgbarray['red'] < 145 && $rgbarray['green'] < 145 & $rgbarray['blue'] < 145) {							$data[$i][$j]=1;						} else {							$data[$i][$j]=0;						}					}				}							}		}				return $data;	}				function readHourDot($picfile) {		$res = imagecreatefrompng($picfile);		$size = getimagesize($picfile);		$this->width = $size[0];		$this->height = $size[1];		$data = array();				for($j = 0; $j < $this->height; ++$j) {			/*			 * 取需要的数据段 			 * popup_module_view_hour.png			 * 25, 245 # 35, 480			 * 			 */						if($j > 30 && $j < 242) {   				for($i=0; $i < $this->width; ++$i) {					if($i >66 && $i < 486) {						$rgb = imagecolorat($res,$i,$j);						$rgbarray = imagecolorsforindex($res, $rgb);						if(($rgbarray['red'] < 50 && $rgbarray['green'] > 180 && $rgbarray['blue'] < 50) || ($rgbarray['red'] < 145 && $rgbarray['green'] < 145 & $rgbarray['blue'] < 145)) {							$data[$i][$j]=1;						} else {							$data[$i][$j]=0;						}					}				}							}		}				return $data;	}		function cutData($data) {		$zimo = $tmp = array();		$num = $len = 0;		$count_start = false;		foreach($data as $k => $v) {			if(in_array(1, $v)) {								$zimo[$num][] = $v;				$count_start = true;				$len++;				if($len >= 6) {  //解决字体连在一起					$len = 0;					$num++; //字数加1				}							} else {				$len = 0;				$count_start = false;			}			if(!$count_start) {				$num++;			}		}		//var_dump(array_keys($zimo));				//对于字母T的修复		$res = $this->createZimoArray($zimo);		//$this->debugPic($zimo[35]);		//die();		//打印完整字模点阵		/*		foreach($zimo as $k => $v) {			if($k == 35) {				echo '<hr />';				$this->debugPic($v);			}		}		*/				//var_dump($res);		end($res);//移动数据指针		$last_two_data = prev($res);				if(!strcmp($last_two_data, '0100000000')) { //说明切割T时存在问题			$last_three_data = prev($res);			$last_three_data_real = $last_three_data . $last_two_data; //补充到T字母中			foreach($res as $k => $v) {				if(!strcmp($v, $last_three_data)) {					$res[$k] = $last_three_data_real;				}			}					}		return $res;	}		//构造字模数组	function createZimoArray($data) {		$str = array();		foreach($data as $k => $v) {			$str[$k] = '';			foreach($v as $ks => $vs) {				$str[$k] .= implode('', $vs);			}		}		return $str;	}		//将数据字模读入文件中	function storeZimo($data) {		$str = $this->createZimoArray($data);		$picwords = APP_CACHE_PATH.'picwords.php';		swritefile($picwords, "<?php\r\nreturn ".var_export($str, true)."\r\n?>");	}	//匹配字模数据	function matchZimo($str_arr) {		$need_str = '';		$picwords = $this->zimo_file;		if(empty($this->zimo_info)) {			$this->zimo_info = include_once($picwords);		}		foreach($str_arr as $k => $v) {			foreach($this->zimo_info as $ks => $vs) {				similar_text($v, $vs, $tmp);				if($tmp > 99)					$need_str .= $ks;			}		}		return $need_str;	}		function debugPic($data) {			echo '<div style="width:5850px">';			foreach($data as $k => $v) {				echo '<div style="float:left">';				foreach($v as $ks => $vs) {					echo $vs."<br />";				}				echo '</div>';			}			echo '</div>';	}	function handleHourData($data) {		$data_info = array();		foreach($data as $k => $v) {			$get = true;			$data_info[$k] = 0;			foreach($v as $ks => $vs) {				if($vs == 1 && $get) {					$get = false;				}				if(!$get) {					$data_info[$k]++;									} else {					unset($data[$k][$ks]);				}			}		}		return $data_info;	}/************************************取数据的方法*******************************/	//总流量	function getPicWords($file) {		$need_str = '';		//读取图片点阵信息		$data = $this->readPicDot($file);				//处理切割到的数据,并写入数组		$data = $this->cutData($data);		//匹配字模数据		$need_str = $this->matchZimo($data);		return $need_str;	}	//得到最大流量速度	function getMaxSpeed($file) {		$need_str = '';				//读取图片点阵信息		$data = $this->readMaxOutDot($file);		//处理切割到的数据,并写入数组		$data = $this->cutData($data);		//匹配字模数据		$need_str = $this->matchZimo($data);		return $need_str;	}	//分析小时图中的流量峰值	function parseFlow($file, $info) {		//得到最大流量速度		$maxflow = floatval($this->getMaxSpeed($file));		//读取图片点阵信息		$data = $this->readHourDot($file);		//数据抽象形变		$data_info = $this->handleHourData($data);				$max = max($data_info);				$radio = (float) ($maxflow / $max); //流量计算比列				$timeradio = ceil($this->hourstep / 60);//每分钟格数				$continued_time = $this->continued * $timeradio;//持续时间用点阵长度量化				$count = 0;		foreach($data_info as $v) {			if($v * $radio > $this->warnning_data) {				$count++;				if($count >= $continued_time) {					echo "ServerID: $info[sid] IP: $info[ip] flow over: ".$this->warnning_data.'<br />'; //发邮件					break;				}			} else {				$count = 0;			}		}	}	}?>


一.文字提取功能介绍

需要操作的图片,下面红字部分是我们需要取出的文字

经过代码处理后得到如下图片
<?php$picWord = new picWords();$picfile = 'popup_module_view.png';//图片路径$data = $picWord->readPicDot($picfile);//读取图片点阵信息?>



此图片由一组0、1表示,相信大家都看的出来这图里面的字符串吧


到此我们已经缩小了我们操作对象的范围,马上问题也来了,我们如何可以得图片中的字符个数及字符

这个问题也是最难的,到此我们就开始切割了

经过代码处理得到如下图片:
<?php$data = $picWord->cutData($data);//处理切割到的数据,并写入数组?>



每一个块都对应一个字符(此时还不是真正的字符,还只是未知数据,等待咱们去转换)

细心的朋友应该看出来了,倒数据第二、三块,其实是表示的一个T,后续代码中对此有单独的处理

在此解释一下,因为我是按每个字符6个像素来宽图和10个像素高度来计算的,或许有同学来问了,那你怎么就一定要用这样两个数字来计算呢?我想说,这些是在对此图片里面的文字观察来的,5,7都不行,所以就选了6作宽度,高度很容易看出来10
<?php$need_str= $picWord->matchZimo($data);//匹配字模数据?>


然后在将保存这些字符串的数组转化为’10101010…’的字符串,以及与字模文件(这里我们先用,后面我们在介绍它)匹配,然后得到我们要的数据



二.生成字模

生成字模的过程跟上面的是一样的,只是在最后需要我们人工去识别、记录保存字符的数组中的字符串与对应的字符,此步聚一定要在上面之前完成,不然上面没有可以用来匹配的字模文件。

或许同学们要说,这还是得人工去识别,不是智能的。但没有现成的字模文件,所以我们必须手动去生成。要是那位同学对于字体字模有研究,一眼可以看出来图片中的文字是用哪种字模同时有此字模文件,那到是可以不用咱们人工生成,直接借来一用即可


好了今天这篇文章就到这里了,取到文件中的固定文字

一个DEMO下载地址,完整的代码,有兴趣的同学可以下载交流一下, 点击下载DEMO
解压文件后运行pick_pic_data.php即可,图片文件也可以在此文件重随意指定

下次我们在介绍如何根据波形来检测超过某个固定值的情况,从而做出回应

回复讨论(解决方案)

多谢分享。。。。。。

谢谢分享。

谢谢分享,学习了。。。。

您好,我有个问题想要请教。 piczimo.php文件中0-9是怎么转换为以下模式的。
'0' => '001111110001100001100100000010010010001001100001100011111100',
'1' => '01000000100100000010011111111000000000100000000010',

那a-z A-Z 呢?望指点谢谢。

声明:
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn