PHP 图片哈希精度建议
PHP Image hashing accuracy suggestion
我正在尝试将图像哈希添加到数据库中。
我的问题是我有 300 万张图片,其中一些图片有 99.999+% 相同。例如 imageA.jpg 和 imageB.jpg 都具有相同的分辨率 800x600,但可以说 imageB.jpg有10个不同的像素:
800x600 = 480000 总像素;
(480000 - 10 像素差异)/ 48000 总像素 = 0.9999791666666667 相似度
为了减少重复,我编写了 PHP class 原型。一切都很好,不是很完美,但很好。主要问题是,即使我设置了最高质量,->recreateFile() 函数每次都会创建一个有点不同的图像。
我正在寻找稳定所有像素的解决方案,即使我会重新创建图像 100 次。
还有其他更好的方法 solution/ideas 来减少我的重复图像吗?
我的PHPclass代码:
<?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;
}
}
在这上面花了很多时间之后,
当前解决方案代码:
<?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;
}
}
我正在尝试将图像哈希添加到数据库中。
我的问题是我有 300 万张图片,其中一些图片有 99.999+% 相同。例如 imageA.jpg 和 imageB.jpg 都具有相同的分辨率 800x600,但可以说 imageB.jpg有10个不同的像素:
800x600 = 480000 总像素;
(480000 - 10 像素差异)/ 48000 总像素 = 0.9999791666666667 相似度
为了减少重复,我编写了 PHP class 原型。一切都很好,不是很完美,但很好。主要问题是,即使我设置了最高质量,->recreateFile() 函数每次都会创建一个有点不同的图像。
我正在寻找稳定所有像素的解决方案,即使我会重新创建图像 100 次。
还有其他更好的方法 solution/ideas 来减少我的重复图像吗?
我的PHPclass代码:
<?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;
}
}
在这上面花了很多时间之后, 当前解决方案代码:
<?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;
}
}