PHP实现搜索相似图片
感知哈希的优点是简单快速,不受图片大小缩放的影响,缺点是图片的内容不能变更。实际应用中,往往采用更强大的pHash算法和SIFT算法,它们能够识别图片的变形。只要变形程度不超过25%,它们就能匹配原图。
感知哈希算法
count < =5 匹配最相似
count > 10 两张不同的图片
var_dump(ImageHash::run(‘./1.png', ‘./psb.jpg'));
- <?php
- class ImageHash {
- const FILE_NOT_FOUND = '-1';
- const FILE_EXTNAME_ILLEGAL = '-2';
- private function __construct() {}
- public static function run($src1, $src2) {
- static $self;
- if(!$self) $self = new static;
- if(!is_file($src1) || !is_file($src2)) exit(self::FILE_NOT_FOUND);
- $hash1 = $self->getHashValue($src1);
- $hash2 = $self->getHashValue($src2);
- if(strlen($hash1) !== strlen($hash2)) return false;
- $count = 0;
- $len = strlen($hash1);
- for($i = 0; $i < $len; $i++) if($hash1[$i] !== $hash2[$i]) $count++;
- return $count <= 10 ? true : false;
- }
- public function getImage($file) {
- $extname = pathinfo($file, PATHINFO_EXTENSION);
- if(!in_array($extname, ['jpg','jpeg','png','gif'])) exit(self::FILE_EXTNAME_ILLEGAL);
- $img = call_user_func('imagecreatefrom'. ( $extname == 'jpg' ? 'jpeg' : $extname ) , $file);
- return $img;
- }
- public function getHashValue($file) {
- $w = 8;
- $h = 8;
- $img = imagecreatetruecolor($w, $h);
- list($src_w, $src_h) = getimagesize($file);
- $src = $this->getImage($file);
- imagecopyresampled($img, $src, 0, 0, 0, 0, $w, $h, $src_w, $src_h);
- imagedestroy($src);
- $total = 0;
- $array = array();
- for( $y = 0; $y < $h; $y++) {
- for ($x = 0; $x < $w; $x++) {
- $gray = (imagecolorat($img, $x, $y) >> 8) & 0xFF;
- if(!isset($array[$y])) $array[$y] = array();
- $array[$y][$x] = $gray;
- $total += $gray;
- }
- }
- imagedestroy($img);
- $average = intval($total / ($w * $h * 2));
- $hash = '';
- for($y = 0; $y < $h; $y++) {
- for($x = 0; $x < $w; $x++) {
- $hash .= ($array[$y][$x] >= $average) ? '1' : '0';
- }
- }
- var_dump($hash);
- return $hash;
- }
- }
var_dump(ImageHash::run('./1.png', './psb.jpg'));
方法二:
- hash($f);
- }
- return $isString ? $result[0] : $result;
- }
- public function checkIsSimilarImg($imgHash, $otherImgHash){
- if (file_exists($imgHash) && file_exists($otherImgHash)){
- $imgHash = $this->run($imgHash);
- $otherImgHash = $this->run($otherImgHash);
- }
- if (strlen($imgHash) !== strlen($otherImgHash)) return false;
- $count = 0;
- $len = strlen($imgHash);
- for($i=0;$i<$len;$i++){
- if ($imgHash{$i} !== $otherImgHash{$i}){
- $count++;
- }
- }
- return $count <= (5 * $rate * $rate) ? true : false;
- }
- public function hash($file){
- if (!file_exists($file)){
- return false;
- }
- $height = 8 * $this->rate;
- $width = 8 * $this->rate;
- $img = imagecreatetruecolor($width, $height);
- list($w, $h) = getimagesize($file);
- $source = $this->createImg($file);
- imagecopyresampled($img, $source, 0, 0, 0, 0, $width, $height, $w, $h);
- $value = $this->getHashValue($img);
- imagedestroy($img);
- return $value;
- }
- public function getHashValue($img){
- $width = imagesx($img);
- $height = imagesy($img);
- $total = 0;
- $array = array();
- for ($y=0;$y<$height;$y++){
- for ($x=0;$x<$width;$x++){
- $gray = ( imagecolorat($img, $x, $y) >> 8 ) & 0xFF;
- if (!is_array($array[$y])){
- $array[$y] = array();
- }
- $array[$y][$x] = $gray;
- $total += $gray;
- }
- }
- $average = intval($total / (64 * $this->rate * $this->rate));
- $result = '';
- for ($y=0;$y<$height;$y++){
- for ($x=0;$x<$width;$x++){
- if ($array[$y][$x] >= $average){
- $result .= '1';
- }else{
- $result .= '0';
- }
- }
- }
- return $result;
- }
- public function createImg($file){
- $ext = $this->getFileExt($file);
- if ($ext === 'jpeg') $ext = 'jpg';
- $img = null;
- switch ($ext){
- case 'png' : $img = imagecreatefrompng($file);break;
- case 'jpg' : $img = imagecreatefromjpeg($file);break;
- case 'gif' : $img = imagecreatefromgif($file);
- }
- return $img;
- }
- public function getFileExt($file){
- $infos = explode('.', $file);
- $ext = strtolower($infos[count($infos) - 1]);
- return $ext;
- }
- }
调用方式如下:
- require_once "Imghash.class.php";
- $instance = ImgHash::getInstance();
- $result = $instance->checkIsSimilarImg('chenyin/IMG_3214.png', 'chenyin/IMG_3212.JPG');
如果$result值为true, 则表明2个图片相似,否则不相似。