Предложение по точности хеширования изображений PHP - PullRequest
0 голосов
/ 08 сентября 2018

Я пытаюсь добавить хэш изображения в базу данных.

Моя проблема в том, что у меня 3 миллиона изображений, и некоторые из них имеют 99.999 +% одинаковых. Например, imageA.jpg и imageB.jpg имеют одинаковое разрешение 800x600, но, скажем, imageB.jpg имеют 10 разных пикселей:

800x600 = 480000 всего пикселей;

(480000 - разница в 10 пикселей) / общее количество пикселей 48000 = 0.9999791666666667 сходство

Чтобы уменьшить количество дубликатов, я написал прототип класса PHP. Все работает отлично, не идеально, но просто отлично. Основная проблема в том, что функция -> refreshateFile () каждый раз создает немного другое изображение, даже если я устанавливаю максимальное качество.

Я ищу решение для стабилизации всех пикселей, даже если бы я воссоздал изображение 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 голосов
/ 05 октября 2018

Потратив много времени на это, текущий код решения:

<?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;
    }
}
...