PHP比较一组图片是否有相似的图片:之两层循环,使用握手计数原理,计算出两两图片对比的组合,并删除重复的图片


说明:

  最近有一个需求,说。一组图片地址,如果两张图片相似,就进行去重。

例如:

  如下图,img_list 中,如果第一个和第二个,图片相同,那么就保留其中一个,其余的依次类推,最终取的一个不重复的,图片img_listing。

 思路:

  至于图片怎么识别为重复的,这里使用的是一个扩展,扩展git地址:https://github.com/jenssegers/imagehash

  这个利用的是,图像哈希。

 Laravel安装扩展

composer require jenssegers/imagehash

去重思路:

  1、N张图片对比后去重,这里就需要每两两进行比较,如果重复,就删除一张。所以,这里两两的组合比对次数为 ((n-1)*n )/2。这其实就是一个握手计数原理。

  2、所以,我们可以按这个逻辑进行写代码。

    步骤一:定义一个方法,传入需要对比的图片地址数组;

    步骤二:使用两层for循环,计算出所有的组合数;

    步骤三:对二中的组合进行哈希比对,如果为重复,即删除第一个键名内容,然后,将删除后的数组再传入到该方法中,如此进行递归调用,最后取的没有重复的数组img。

代码如下:

    /**
     * 删除数组中相似的图片地址方法
     * $img_list 图片数组list
     * $img_count 数组长度
     * $img_hash 图片地址与的散列值的映射数组,承载,减少重复处理次数,优化处理时间
     */
    public function deleteSha1Img($img_list, $img_count, $img_hash = []){
        try{
            $hasher = new ImageHash(new DifferenceHash());
            //两层循环,使用握手计数原理,计算出两两图片对比的组合
            for ($i=0; $i < $img_count; $i++) {
                for ($i1 = $img_count - 1; $i1 > $i; $i1 --) {
                    if(empty($img_hash[$img_list[$i]])){//承载数组中,没有,直接获取
                        $value1_sh = $hasher->hash($img_list[$i]);//获取图片的散列值对象 $hash->toHex();
                        $img_hash[$img_list[$i]] = $value1_sh;//进行赋值
                    }else{
                        $value1_sh = $img_hash[$img_list[$i]];//有,直接读取
                    }
                    
                    if(empty($img_hash[$img_list[$i1]])){
                        $value2_sh = $hasher->hash($img_list[$i1]);
                        $img_hash[$img_list[$i1]] = $value2_sh;
                    }else{
                        $value2_sh = $img_hash[$img_list[$i1]];
                    }
                    $sh = $hasher->distance($value1_sh, $value2_sh);//进行相似比较
                    if($sh <= 5){
                        unset($img_list[$i]);//两张相似的,直接删除第一张
                        $img_list = array_values($img_list);//对新数组进行重新排序
                        return $this->deleteSha1Img($img_list, count($img_list), $img_hash);
                    }
                }
            }
        }catch(\Exception $e){
            throw new \Exception($e->getMessage());
        }
        return $img_list;
    }

结束:

  记录一下,发现最近经常写递归,递归注意返回值,不然会出现,明明有值,却调用的时候,返回null。