PHP Image哈希精度建议

时间:2018-09-08 15:20:29

标签: php image hash duplicates imagick

我正在尝试将图像哈希添加到数据库中。

我的问题是我有300万张图片,其中有些是99.999 +%的图片。例如, imageA.jpg imageB.jpg 的分辨率均为800x600,但是 imageB.jpg 则具有10个不同的像素:

800x600 =总480000像素;

(480000-10像素差异)/ 48000总像素= 0.9999791666666667相似性

为了减少重复,我编写了PHP类原型。一切都很好,不是很好,但是很好。主要问题是,即使我设置了最高质量,每次-> recreateFile()函数也会创建一点不同的图像。

我正在寻找一种可以稳定所有像素的解决方案,即使我会重新创建图像100次。

还有其他更好的解决方案/想法可以减少重复的图像吗?

我的PHP类代码:

<?php

/**
 * Class HashImage
 * @package App\Cryptography
 */
class HashImage
{
    /**
     *
     */
    const IMAGE_PIXELS = 32;
    /**
     *
     */
    const IMAGE_QUALITY = 100;
    /**
     *
     */
    const IMAGE_FORMAT = 'jpg';
    /**
     *
     */
    const IMAGE_ALGORITHM = 'sha256';
    /**
     * @var string
     */
    private $file;
    /**
     * @var
     */
    private $hash;

    /**
     * HashImage constructor.
     * @param string $file
     */
    public function __construct(string $file)
    {
        $this->file = $file;
    }

    /**
     * @return string
     * @throws \ImagickException
     */
    public function getHash(): string
    {
        $this
            ->recreateFile()
            ->setHash(1)
            ->setHash(2)
            ->setHash(0);
        return hash(self::IMAGE_ALGORITHM, $this->hash);
    }


    /**
     * @param int $type
     * @return self
     * @throws \ImagickException
     */
    private function setHash(int $type): self
    {
        $image = new \Imagick($this->file);
        $image->setImageDepth(8);
        $image->setGravity(\Imagick::GRAVITY_CENTER);
        $image->quantizeImage(15, \Imagick::COLORSPACE_RGB, 255, false, false);
        $image->setImageFormat('PNG');
        if ($type === 1) {
            $width = self::IMAGE_PIXELS;
            $height = self::IMAGE_PIXELS / 2;
        } elseif ($type === 2) {
            $width = self::IMAGE_PIXELS / 2;
            $height = self::IMAGE_PIXELS;
        } else {
            $width = self::IMAGE_PIXELS;
            $height = self::IMAGE_PIXELS;
        }
        $image->cropThumbnailImage($width, $height);
        $img = imagecreatefromstring($image->getImageBlob());
        for ($x = 0; $x < $width; $x++) {
            for ($y = 0; $y < $height; $y++) {
                $colors = imagecolorsforindex($img, imagecolorat($img, $x, $y));
                $this->hash .= round((round((round((round(($colors['red'] + 1) / 2, 0, PHP_ROUND_HALF_DOWN) + 1) / 2, 0, PHP_ROUND_HALF_DOWN) + 1) / 2, 0, PHP_ROUND_HALF_DOWN) + 1) / 2, 0, PHP_ROUND_HALF_DOWN)
                    . round((round((round((round(($colors['green'] + 1) / 2, 0, PHP_ROUND_HALF_DOWN) + 1) / 2, 0, PHP_ROUND_HALF_DOWN) + 1) / 2, 0, PHP_ROUND_HALF_DOWN) + 1) / 2, 0, PHP_ROUND_HALF_DOWN)
                    . round((round((round((round(($colors['blue'] + 1) / 2, 0, PHP_ROUND_HALF_DOWN) + 1) / 2, 0, PHP_ROUND_HALF_DOWN) + 1) / 2, 0, PHP_ROUND_HALF_DOWN) + 1) / 2, 0, PHP_ROUND_HALF_DOWN);
            }
        }
        return $this;
    }

    /**
     * @return self
     */
    private function optimizeFile(): self
    {
        exec('/usr/bin/jpegoptim --strip-all --all-progressive ' . $this->file);
        return $this;
    }

    /**
     * @return self
     * @throws \ImagickException
     */
    private function recreateFile(): self
    {
        $image = new \Imagick($this->file);
        $image->setImageFormat(self::IMAGE_FORMAT);
        $image->setCompression(\Imagick::COMPRESSION_JPEG);
        $image->setCompressionQuality(self::IMAGE_QUALITY);
        $image->writeImage($this->file);
        return $this;
    }
}

1 个答案:

答案 0 :(得分:0)

花了很多时间之后, 当前解决方案代码:

<?php declare(strict_types=1);

namespace App\Cryptography;
/**
 * Class HashImage
 * @package App\Cryptography
 */
class HashImage
{
    /**
     * Hashing accuracy
     */
    const HASHING_PIXELS = 64;
    /**
     * Return encryption algorithm
     */
    const HASHING_ALGORITHM = 'sha256';
    /**
     * @var string
     */
    private $file;
    /**
     * @var string
     */
    private $hash;

    /**
     * HashImage constructor.
     * @param string $file
     */
    public function __construct(string $file)
    {
        $this->file = $file;
    }

    /**
     * @return string
     * @throws \ImagickException
     */
    public function getHash(): string
    {
        $this
            ->setHash(1)
            ->setHash(2)
            ->setHash(0);
        return hash(self::HASHING_ALGORITHM, $this->hash);
    }

    /**
     * @param int $type
     * @return self
     * @throws \ImagickException
     */
    private function setHash(int $type): self
    {
        $image = new \Imagick($this->file);
        $image->setImageFormat('PNG');
        $image->setImageDepth(8);
        $image->setGravity(\Imagick::GRAVITY_CENTER);
        $width = $height = self::HASHING_PIXELS;
        if ($type === 1) {
            $height = self::HASHING_PIXELS / 2;
        } elseif ($type === 2) {
            $width = self::HASHING_PIXELS / 2;
        }
        $image->cropThumbnailImage($width, $height);
        $img = imagecreatefromstring($image->getImageBlob());
        for ($x = 0; $x < $width; $x++) {
            for ($y = 0; $y < $height; $y++) {
                $colors = imagecolorsforindex($img, imagecolorat($img, $x, $y));
                $this->hash .= $colors['red'] . $colors['green'] . $colors['blue'];
            }
        }
        return $this;
    }
}