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

WBOY
Freigeben: 2016-06-23 14:19:00
Original
1540 Leute haben es durchsucht

本帖最后由 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;			}		}	}	}?>
Nach dem Login kopieren


一.文字提取功能介绍

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

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



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


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

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

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



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

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

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


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



二.生成字模

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

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


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

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

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

回复讨论(解决方案)

多谢分享。。。。。。

谢谢分享。

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

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

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

Verwandte Etiketten:
Quelle:php.cn
Erklärung dieser Website
Der Inhalt dieses Artikels wird freiwillig von Internetnutzern beigesteuert und das Urheberrecht liegt beim ursprünglichen Autor. Diese Website übernimmt keine entsprechende rechtliche Verantwortung. Wenn Sie Inhalte finden, bei denen der Verdacht eines Plagiats oder einer Rechtsverletzung besteht, wenden Sie sich bitte an admin@php.cn
Beliebte Tutorials
Mehr>
Neueste Downloads
Mehr>
Web-Effekte
Quellcode der Website
Website-Materialien
Frontend-Vorlage
Über uns Haftungsausschluss Sitemap
Chinesische PHP-Website:Online-PHP-Schulung für das Gemeinwohl,Helfen Sie PHP-Lernenden, sich schnell weiterzuentwickeln!