侯体宗的博客
  • 首页
  • 人生(杂谈)
  • 技术
  • 关于我
  • 更多分类
    • 文件下载
    • 文字修仙
    • 中国象棋ai
    • 群聊
    • 九宫格抽奖
    • 拼图
    • 消消乐
    • 相册

PHP图像识别技术原理与实现

php  /  管理员 发布于 7年前   130

其实图像识别技术与我们平时做的密码验证之类的没有什么区别,都是事先把要校验的数据入库,然后使用时将录入(识别)的数据与库中的数据做对比,只不过图像识别技术有一部分的容错性,而我们平时的密码验证是要100%匹配。

前几天,有朋友谈到做游戏点击抽奖,识别图片中的文字,当时立马想到的就是js控制或者flash做遮罩层,感觉这种办法是最方便快捷效果好,而且节省服务器资源,但是那边提的要求竟然是通过php识别图像中的文字。

赶巧那两天的新闻有:1、马云人脸识别支付;2、12306使用新的验证码,说什么现在国内的抢票软件都不能用了,发布不到一天就被破解。然后又很凑巧的那天早上看了一篇Java的图像识别技术文章。于是就琢磨着看一下PHP的图像识别技术。

其实所谓的图像识别,已经不是什么新技术了,起码我找到的资料都是很早之前的了。只不过我一直没涉及到这方面的工作,就一直没看过。

先说下这次实验的需求:有一张图片,里面三个位置分别有三个数字,要求取出相应位置的数字的值。(眼尖的同学可能会看出下面的代码是我拿的别人的,没错,的确是我直接copy别人并删减的,毕竟我对这些也是浅尝辄止,最后会贴出原作者的初始代码)

class gjPhone{  protected $imgPath; // 图片路径  protected $imgSize; // 图片大小  protected $hecData; // 分离后数组  protected $horData; // 横向整理的数据  protected $verData; // 纵向整理的数据  function __construct ($path)  {    $this->imgPath = $path;  }  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;  }  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;  }  public function showPhone ($ndatas)  {    error_reporting(0);    $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;  }  /**   * 初始数据   */  public function initData ($numStr)  {    $result = null;    $data = array(        '1' => '00000000111000000000000001110000000001001000100000000010100011000000000011000110000000000110000100000000010110011000000',        '5' => '00000000001000000000000000010000000000100100100000000000101001110000000000100000110000000011000000100000001101000010000',        '10' => '00000011100011100000000011001100100100100010010001000110000100100010001100001001000100011000010010001001001001100010100'    );    foreach ($data as $key => $val) {      similar_text($numStr, $val, $pre);      if ($pre > 95) { // 相似度95%以上        $result = $key;        break;      }    }    return $result;  }}$imgurl = 'jd.png';list ($width, $heght, $type, $attr) = getimagesize($imgurl);$new_w = 17;$new_h = 11;$thisimage = imagecreatetruecolor($new_w, $new_h); // $new_w, $new_h 为裁剪后的图片宽高$background = imagecolorallocate($thisimage, 255, 255, 255);imagefilledrectangle($thisimage, 0, 0, $new_w, $new_h, $background);$oldimg = imagecreatefrompng($imgurl); // 载入原始图片        // 首先定位要取图的位置(这里可以通过前端js或者其他手段定位,由于我这是测试,所以就ps定位并写死了)$weizhi = array(    '1' => 165,    '5' => 308,    '10' => 456);foreach ($weizhi as $wwzz) {  $src_y = 108;  imagecopy($thisimage, $oldimg, 0, 0, $wwzz, $src_y, $new_w, $new_h); // $src_y,$new_w为原图中裁剪区域的左上角坐标拷贝图像的一部分将src_im图像中坐标从src_x,src_y开始,宽度为src_w,高度为src_h的一部分拷贝到dst_im图像中坐标为dst_x和dst_y的位置上。  $tem_png = 'tem_1.png';  imagepng($thisimage, __DIR__ . '/' . $tem_png); // 通过定位从原图中copy出想要识别的位置并生成新的缓存图,用以后面的图像识别类使用。    $gjPhone = new gjPhone($tem_png); // 实例化类  $gjPhone->getHec(); // 进行图像像素分离  $horData = $gjPhone->magHorData(); // 将分离出是数据转成01表示的图像、这里可以根据自己喜好定  $phone = $gjPhone->showPhone($horData); // 将转换好的01表示的数据与库中的数据进行匹配,匹配度95以上就算成功,库这里由于是做测试就直接写了数组  echo '| ' . $phone . ' | ';}

如此看来,其实12306验证码被破解也算是有情可原了,也没必要那么的口诛笔伐了罢。只要不断的抓验证码图片并转成自己程序可读的数据存入库里,然后验证的时候进行匹配就可以了。那么阿里的人脸识别支付原理也算是理解了,只不过他们做的可能会很精细。

前端时间有看到阿里云的一个验证码形式,刚开始感觉可能会好点,现在看来,只要有心,其实也是可以破解的啊。

好了,下面是原作代码。

/** * 电话号码识别. * @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 .= "" . $v . "";          } else {$c .= $v;          }        }        $c .= "
"; } } 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 "===============横向数据==============


";$gjPhone->drawWH($horData);// 画出纵向数据$verData = $gjPhone->magVerData($horData);echo "


===============纵向数据==============< br/>

";$gjPhone->drawWH($verData);// 输出电话$phone = $gjPhone->showPhone($verData);echo "


===============电话==============


" . $phone;

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。

您可能感兴趣的文章:

  • PHP图像处理技术实例总结【绘图、水印、验证码、图像压缩】
  • PHP图片裁剪函数(保持图像不变形)
  • PHP中绘制图像的一些函数总结
  • php图像处理函数大全(推荐收藏)
  • php使用imagick模块实现图片缩放、裁剪、压缩示例
  • 基于PHP实现等比压缩图片大小
  • 浅谈关于PHP解决图片无损压缩的问题
  • PHP添加图片水印、压缩、剪切的封装类
  • php高清晰度无损图片压缩功能的实现代码
  • PHP的图像处理实例小结【文字水印、图片水印、压缩图像等】


  • 上一条:
    遍历指定目录,并存储目录内所有文件属性信息的php代码
    下一条:
    PHP对称加密函数实现数据的加密解密
  • 昵称:

    邮箱:

    0条评论 (评论内容有缓存机制,请悉知!)
    最新最热
    • 分类目录
    • 人生(杂谈)
    • 技术
    • linux
    • Java
    • php
    • 框架(架构)
    • 前端
    • ThinkPHP
    • 数据库
    • 微信(小程序)
    • Laravel
    • Redis
    • Docker
    • Go
    • swoole
    • Windows
    • Python
    • 苹果(mac/ios)
    • 相关文章
    • Laravel从Accel获得5700万美元A轮融资(0个评论)
    • PHP 8.4 Alpha 1现已发布!(0个评论)
    • 用Time Warden监控PHP中的代码处理时间(0个评论)
    • 在PHP中使用array_pop + yield实现读取超大型目录功能示例(0个评论)
    • Property Hooks RFC在PHP 8.4中越来越接近现实(0个评论)
    • 近期文章
    • 在windows10中升级go版本至1.24后LiteIDE的Ctrl+左击无法跳转问题解决方案(0个评论)
    • 智能合约Solidity学习CryptoZombie第四课:僵尸作战系统(0个评论)
    • 智能合约Solidity学习CryptoZombie第三课:组建僵尸军队(高级Solidity理论)(0个评论)
    • 智能合约Solidity学习CryptoZombie第二课:让你的僵尸猎食(0个评论)
    • 智能合约Solidity学习CryptoZombie第一课:生成一只你的僵尸(0个评论)
    • 在go中实现一个常用的先进先出的缓存淘汰算法示例代码(0个评论)
    • 在go+gin中使用"github.com/skip2/go-qrcode"实现url转二维码功能(0个评论)
    • 在go语言中使用api.geonames.org接口实现根据国际邮政编码获取地址信息功能(1个评论)
    • 在go语言中使用github.com/signintech/gopdf实现生成pdf分页文件功能(95个评论)
    • gmail发邮件报错:534 5.7.9 Application-specific password required...解决方案(0个评论)
    • 近期评论
    • 122 在

      学历:一种延缓就业设计,生活需求下的权衡之选中评论 工作几年后,报名考研了,到现在还没认真学习备考,迷茫中。作为一名北漂互联网打工人..
    • 123 在

      Clash for Windows作者删库跑路了,github已404中评论 按理说只要你在国内,所有的流量进出都在监控范围内,不管你怎么隐藏也没用,想搞你分..
    • 原梓番博客 在

      在Laravel框架中使用模型Model分表最简单的方法中评论 好久好久都没看友情链接申请了,今天刚看,已经添加。..
    • 博主 在

      佛跳墙vpn软件不会用?上不了网?佛跳墙vpn常见问题以及解决办法中评论 @1111老铁这个不行了,可以看看近期评论的其他文章..
    • 1111 在

      佛跳墙vpn软件不会用?上不了网?佛跳墙vpn常见问题以及解决办法中评论 网站不能打开,博主百忙中能否发个APP下载链接,佛跳墙或极光..
    • 2016-10
    • 2016-11
    • 2017-06
    • 2017-07
    • 2017-08
    • 2017-09
    • 2017-11
    • 2017-12
    • 2018-01
    • 2018-02
    • 2018-03
    • 2020-03
    • 2020-04
    • 2020-05
    • 2020-06
    • 2020-07
    • 2020-09
    • 2021-02
    • 2021-03
    • 2021-04
    • 2021-05
    • 2021-06
    • 2021-07
    • 2021-08
    • 2021-09
    • 2021-10
    • 2021-11
    • 2021-12
    • 2022-01
    • 2022-02
    • 2022-05
    • 2022-06
    • 2022-07
    • 2022-08
    • 2022-09
    • 2022-10
    • 2022-11
    • 2022-12
    • 2023-01
    • 2023-02
    • 2023-03
    • 2023-04
    • 2023-05
    • 2023-06
    • 2023-07
    • 2023-08
    • 2023-09
    • 2023-10
    • 2023-11
    • 2023-12
    • 2024-01
    • 2024-02
    • 2024-03
    • 2024-04
    • 2024-05
    • 2024-06
    • 2024-07
    • 2024-09
    Top

    Copyright·© 2019 侯体宗版权所有· 粤ICP备20027696号 PHP交流群

    侯体宗的博客