1、场景
最近在学习图片处理,就是特意把数字生成一个图片,然后再用程序去识别图片的数字。这就有了一下的学习过程。
2、原理分析
2.1 首先是将图片像素化,二值化,然后和字模去对比(需要相对于配置字模)
||
\/
||
\/
2.2 然后再这每个数字分别取出来,与字模库做比较,匹配成功即可获取对应的值
3、源码
3.1 经过我修改后的代码
使用说明:通过传入的图片地址获取图片的数字,$imgPath为图片路径
执行步骤:先把图片像素化,二值化,保存数组,先横向,再纵向,只要因为纵向方便处理单独数字,然后把纵向的数据跟字模库进行匹配,当匹配率达到95%以上即认为识别成功。
//【获取图片数字】
//$imgPath:图片路径
private function getPhoneByImg($imgPath){ $gjPhone = new GjPhone($imgPath);
// 进行颜色分离
$gjPhone->getHec();
// 画出横向数据
$horData = $gjPhone->magHorData();
//echo "===============横向数据==============<br/><br/><br/>";
//$gjPhone->drawWH($horData);
// 画出纵向数据
$verData = $gjPhone->magVerData($horData);
//echo "<br/><br/><br/>===============纵向数据==============< br/><br/><br/>";
//$gjPhone->drawWH($verData); // 输出电话 $phone = $gjPhone->showPhone($verData);
//echo "<br/><br/><br/>===============电话==============<br /><br/><br/>";
//$this->show($phone); return $phone; }
<?php
namespace common\models; /**
* 电话号码识别.
* @author by zsc for 2010.03.24
*/
class GjPhone
{ protected $imgPath; // 图片路径
protected $imgSize; // 图片大小
protected $hecData; // 分离后数组
protected $horData; // 横向整理的数据
protected $verData; // 纵向整理的数据
function __construct ($path)
{
$this->imgPath = $path;
} /**
* 颜色分离转换...
*
* @param unknown_type $path
* @return unknown
*/
public function getHec ()
{
$size = getimagesize($this->imgPath);
$res = imagecreatefrompng($this->imgPath);
for ($i = 0; $i < $size[1]; ++ $i) {
for ($j = 0; $j < $size[0]; ++ $j) {
$rgb = imagecolorat($res, $j, $i);
$rgbarray = imagecolorsforindex($res, $rgb);
if ($rgbarray['red'] < 125 || $rgbarray['green'] < 125 ||
$rgbarray['blue'] < 125) {
$data[$i][$j] = 1;
} else {
$data[$i][$j] = 0;
}
}
}
$this->imgSize = $size;
$this->hecData = $data;
} /**
* 颜色分离后的数据横向整理...
*
* @return unknown
*/
public function magHorData ()
{
$data = $this->hecData;
$size = $this->imgSize;
$z = 0;
for ($i = 0; $i < $size[1]; ++ $i) {
if (in_array('1', $data[$i])) {
$z ++;
for ($j = 0; $j < $size[0]; ++ $j) {
if ($data[$i][$j] == '1') {
$newdata[$z][$j] = 1;
} else {
$newdata[$z][$j] = 0;
}
}
}
}
return $this->horData = $newdata;
} /**
* 整理纵向数据...
*
* @return unknown
*/
public function magVerData ($newdata)
{
$i_length = count($newdata[1]);
$j_length = count($newdata)+1;
for ($i = 0; $i < $i_length; ++ $i) {
for ($j = 1; $j < $j_length; ++ $j) {
$ndata[$i][$j] = $newdata[$j][$i];
}
} $ndatas= [];
$sum = count($ndata);
$c = 0;
for ($a = 0; $a < $sum; $a ++) {
$value = $ndata[$a];
if (in_array(1, $value)) {
$ndatas[$c] = $value;
$c ++;
} elseif (is_array($ndatas)) {
$b = $c - 1;
if (isset($ndatas[$b]) && in_array(1, $ndatas[$b])) {
$ndatas[$c] = $value;
$c ++;
}
}
} return $this->verData = $ndatas;
} /**
* 显示电话号码...
*
* @return unknown
*/
public function showPhone ($ndatas)
{
$phone = '';
$d = 0;
$ndArr = [];
$ndArr[0] = '';
foreach ($ndatas as $key => $val) { if (in_array(1, $val)) { foreach ($val as $k => $v) {
$ndArr[$d] .= $v;
}
}else{
$d ++;
$ndArr[$d] = '';
} }
array_pop($ndArr);
//return $ndArr; foreach ($ndArr as $key01 => $val01) {
$phone .= $this->initData($val01);
}
return $phone;
} /**
* 分离显示...
*
* @param unknown_type $dataArr
*/
function drawWH ($dataArr)
{
$c = '';
if (is_array($dataArr)) {
foreach ($dataArr as $key => $val) {
foreach ($val as $k => $v) {
if ($v == 0) {
$c .= "<font color='grend'>" . $v . "</font>";
} else {
$c .= $v;
}
}
$c .= "<br/>";
}
}
echo $c;
} /**
* 初始数据...
*
* @param unknown_type $numStr
* @return unknown
*/
public function initData ($numStr)
{
//return 1;
$result = '';
$data = array(
0 => '00011110000011111100011000011011000000111100000011011000011000111111000001111000',
1 => '001000000101100000011111111111111111111100000000010000000001',
2 => '00100000010110000011110000011110000011011000011001110011000101111000010011000001',
//3 => '001000000010011000000011110000000001110000000001110000110001110000110001011001110011011111011111000110001100',
3=> '01000000101100000011100000000110001000011000100001110111001101110111100010001100',
//4 => '000000001100000000111100000001111100000011101100000111001100001100001100011000001100111111111111111111111111000000001100000000000100',
4 => '00000110000000111000000110100000110010000110001000111111111111111111110000001000',
5 => '11111001001111100110100010001110010000011001000001100110001110001111100000011100',
6 => '00111111000111111110110001001110001000011000100001110011001101100111100000001100',
//7 => '110000000000110000000111110000111111110001110000110111000000111100000000111000000000111000000000',
7 => '10000000111000000111100000110010000110001000110000100110000011110000001110000000',
//8 => '000100011110011111111111110011100001110001100001110001100001110001100001110011100001011111111111000100011110',
8 => '00100011000111011110110111001110001000011000100001110111001101110111100010001100',
9 => '00110000000111100110110011001110000100011000010001110010001101111111100011111100', '-' => '00000100000000010000000001000000000100000000010000000001000000000100000000010000'
); foreach ($data as $key => $val) {
similar_text($numStr, $val, $pre);
if ($pre > 95) { // 相似度95%以上 $result .= $key;
break;
}
}
return $result;
}
}
GjPhone.php
3.2 引用的源码
/**
* 电话号码识别.
* @author by zsc for 2010.03.24
*/
class gjPhone
{ protected $imgPath; // 图片路径
protected $imgSize; // 图片大小
protected $hecData; // 分离后数组
protected $horData; // 横向整理的数据
protected $verData; // 纵向整理的数据
function __construct ($path)
{
$this->imgPath = $path;
} /**
* 颜色分离转换...
*
* @param unknown_type $path
* @return unknown
*/
public function getHec ()
{
$size = getimagesize($this->imgPath);
$res = imagecreatefrompng($this->imgPath);
for ($i = 0; $i < $size[1]; ++ $i) {
for ($j = 0; $j < $size[0]; ++ $j) {
$rgb = imagecolorat($res, $j, $i);
$rgbarray = imagecolorsforindex($res, $rgb);
if ($rgbarray['red'] < 125 || $rgbarray['green'] < 125 ||
$rgbarray['blue'] < 125) {
$data[$i][$j] = 1;
} else {
$data[$i][$j] = 0;
}
}
}
$this->imgSize = $size;
$this->hecData = $data;
} /**
* 颜色分离后的数据横向整理...
*
* @return unknown
*/
public function magHorData ()
{
$data = $this->hecData;
$size = $this->imgSize;
$z = 0;
for ($i = 0; $i < $size[1]; ++ $i) {
if (in_array('1', $data[$i])) {
$z ++;
for ($j = 0; $j < $size[0]; ++ $j) {
if ($data[$i][$j] == '1') {
$newdata[$z][$j] = 1;
} else {
$newdata[$z][$j] = 0;
}
}
}
}
return $this->horData = $newdata;
} /**
* 整理纵向数据...
*
* @return unknown
*/
public function magVerData ($newdata)
{
for ($i = 0; $i < 132; ++ $i) {
for ($j = 1; $j < 13; ++ $j) {
$ndata[$i][$j] = $newdata[$j][$i];
}
} $sum = count($ndata);
$c = 0;
for ($a = 0; $a < $sum; $a ++) {
$value = $ndata[$a];
if (in_array(1, $value)) {
$ndatas[$c] = $value;
$c ++;
} elseif (is_array($ndatas)) {
$b = $c - 1;
if (in_array(1, $ndatas[$b])) {
$ndatas[$c] = $value;
$c ++;
}
}
} return $this->verData = $ndatas;
} /**
* 显示电话号码...
*
* @return unknown
*/
public function showPhone ($ndatas)
{
$phone = null;
$d = 0;
foreach ($ndatas as $key => $val) {
if (in_array(1, $val)) {
foreach ($val as $k => $v) {
$ndArr[$d] .= $v;
}
}
if (! in_array(1, $val)) {
$d ++;
}
}
foreach ($ndArr as $key01 => $val01) {
$phone .= $this->initData($val01);
}
return $phone;
} /**
* 分离显示...
*
* @param unknown_type $dataArr
*/
function drawWH ($dataArr)
{
if (is_array($dataArr)) {
foreach ($dataArr as $key => $val) {
foreach ($val as $k => $v) {
if ($v == 0) {
$c .= "<font color='#FFFFFF'>" . $v . "</font>";
} else {
$c .= $v;
}
}
$c .= "<br/>";
}
}
echo $c;
} /**
* 初始数据...
*
* @param unknown_type $numStr
* @return unknown
*/
public function initData ($numStr)
{
$result = null;
$data = array(
0 => '000011111000001111111110011000000011110000000001110000000001110000000001110000000001011000000011011100000111000111111100000001110000',
1 => '011000000000011000000000111111111111111111111111',
2 => '001000000011011000000111110000001101110000011001110000011001110000110001111001100001011111100001000110000001',
3 => '001000000010011000000011110000000001110000000001110000110001110000110001011001110011011111011111000110001100',
4 => '000000001100000000111100000001111100000011101100000111001100001100001100011000001100111111111111111111111111000000001100000000000100',
5 => '111111000001111111000001110001000001110001000001110001100001110001100001110000110011110000111111000000001100',
6 => '000011111000001111111110011000110011110001100001110001100001110001100001110001100001010001110011010000111111000000001100',
7 => '110000000000110000000111110000111111110001110000110111000000111100000000111000000000111000000000',
8 => '000100011110011111111111110011100001110001100001110001100001110001100001110011100001011111111111000100011110',
9 => '001111000000011111100001110000110001110000110001110000110001110000110001011000100001011111100111000111111110000001110000'
);
foreach ($data as $key => $val) {
similar_text($numStr, $val, $pre);
if ($pre > 95) { // 相似度95%以上
$result = $key;
break;
}
}
return $result;
}
} $imgPath = "http://bj.ganji.com/tel/5463013757650d6c5e31093e563c51315b6c5c6c5237.png";
$gjPhone = new gjPhone($imgPath);
// 进行颜色分离
$gjPhone->getHec();
// 画出横向数据
$horData = $gjPhone->magHorData();
echo "===============横向数据==============<br/><br/><br/>";
$gjPhone->drawWH($horData);
// 画出纵向数据
$verData = $gjPhone->magVerData($horData);
echo "<br/><br/><br/>===============纵向数据==============< br/><br/><br/>";
$gjPhone->drawWH($verData); // 输出电话
$phone = $gjPhone->showPhone($verData);
echo "<br/><br/><br/>===============电话==============<br /><br/><br/>" . $phone;
gjphone.php
4、扩展说明
只要适当修改字模库,便可识别字母,特殊字符等,按照纵向数据,修改字模库即可。
5 查阅文章的地址
学习过程难免需要大量阅读别人的文章和分析,本人初次接触,收获良多,感谢分享的人!
原文地址1:http://www.jb51.net/article/95854.htm
原文地址2:http://www.jb51.net/article/78645.htm