PHP-php图片对比的问题?

意见反馈 意见反馈 主题:991 回复:2082

PHP-php图片对比的问题?

甜柠檬 发布于 2017-05-15 字数 172 浏览 1050 回复 4

一个存放图片目录,里面有很多图,但有相当大的一部分只是命名不同而内容一样。
想写一个方法来对比目录的下的图片,相同的只保留一张,其他的删除。不知如何能高效的完成?

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

支持 Markdown 语法,需要帮助?

评论(4

泛泛之交 2017-07-06 4 楼

用文件大小和哈希值组合做一个文件的key,如果key有重复的就删除文件。
不同文件出现相同key的几率非常小,如果不是要求高度安全的场合可以认为不会重复。

想挽留 2017-06-25 3 楼

MD5 最好了,比较准确

归属感 2017-06-24 2 楼

必须完全相同吗?
网上有个计算图片的相似度来判断图片是否一样的:
1、缩小尺寸。将图片缩小到8×8的尺寸,总共64个像素。这一步的作用是去除图片的细节,只保留结构、明暗等基本信息,摒弃不同尺寸、比例带来的图片差异。
2、简化色彩。将缩小后的图片,转为64级灰度。也就是说,所有像素点总共只有64种颜色。
3、计算平均值。计算所有64个像素的灰度平均值。
4、比较像素的灰度。将每个像素的灰度,与平均值进行比较。大于或等于平均值,记为1;小于平均值,记为0。
5、计算哈希值。将上一步的比较结果,组合在一起,就构成了一个64位的整数,这就是这张图片的指纹。组合的次序并不重要,只要保证所有图片都采用同样次序就行了。得到指纹以后,就可以对比不同的图片,看看64位中有多少位是不一样的。

<?php
/**

  • 相似图片搜索hash的php实现

  • @author welefen

  • */
    class Imghash{

    private static $_instance = null;

    public $rate = 2;

    public static function getInstance(){
    if (self::$_instance === null){
    self::$_instance = new self();
    }
    return self::$_instance;
    }
    public function run($file){
    if (!function_exists('imagecreatetruecolor')){
    throw new Exception('must load gd lib', 1);
    }
    $isString = false;
    if (is_string($file)){
    $file = array($file);
    $isString = true;
    }
    $result = array();
    foreach ($file as $f){
    $result[] = $this->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('images/IMG_3214.png', 'images/IMG_3212.JPG');
?>

参考:
图片相似搜索的简单原理

泛泛之交 2017-06-06 1 楼

首先先逐个遍历目录:
1、先比较两个文件的扩展名,如果扩展名不一样,那文件肯定就不一样。
2、再检测两个文件的大小,如果大小不相等,则也不是相同的文件。
3、扩展名一样,大小也一样,那么再用Md5检测两个文件的内容

这样逐步检测应该效率不会很低,因为前两个步骤基本上都已经过滤掉百分之九十的文件了。慢的也只是MD5文件内容,而这个基本上不会太多