В любом проекте человеческий фактор никто не отменял, и если пользователи самостоятельно грузят картинки на сайт – появления дубликатов не избежать. Когда доходит до тысяч файлов, глазами всего не пересмотреть, а повторяющиеся картинки мало того что никому не нужны, так еще и занимают место, тратят ресурс и в конце концов тормозят работу.

Потому рано или поздно встает вопрос автоматизации процесса поиска повторов, и тут мы рассмотрим основные, а так же попробуем в деле.


Сравнение файлов через создание hash


Одним из способов определения дубликатов является сравнение файлов путем генерации хеш-значения из содержимого заданного файла.

Простой пример вычисления хеша изображения:

<?php
imagecreatefrompng('image.png');
echo hash_file('md5', 'image.png');
?>

Результат выглядит примерно так: bff8b4bc8b5c1c1d5b3211dfb21d1e76
Если хеши двух изображений совпадают – изображения одинаковые.



ImageMagick


Функция обработки изображений Imagick::compareImages возвращает массив, который содержит восстановленное изображение и разницу между изображениями.

Пример использования при сравненни двух изображений:

<?php
header("Content-Type: image/png");
$image1 = new imagick("image1.png");
$image2 = new imagick("image2.png");
$result = $image1->compareImages($image2, Imagick::METRIC_MEANSQUAREERROR);
$result[0]->setImageFormat("png");

echo $result[0];
?>


PHP библиотеки


Для быстрого поиска дубликатов необходимо установить библиотеки gd2 и libpuzzle.

Установка gd2 и рестарт сервера apache:

sudo apt-get install php5-gd && sudo service apache2 restart

Установка libpuzzle:

sudo apt-get install libpuzzle-php

Libpuzzle создана для быстрого поиска визуального сходства изображений (GIF, PNG, JPG). Библиотека будет работать даже если изображения были слегка изменены (ресайз, сжатие, изменения цвета). Libpuzzle довольно проста в использовании:

Вычисление подписи для двух ихображений:

$cvec1 = puzzle_fill_cvec_from_file('img1.jpg');
$cvec2 = puzzle_fill_cvec_from_file('img2.jpg');

Вычисление расстояния между подписями:

$d = puzzle_vector_normalized_distance($cvec1, $cvec2);

Проверка изображений на схожесть:

if ($d < PUZZLE_CVEC_SIMILARITY_LOWER_THRESHOLD) {
  echo "Pictures are looking similar\n";
} else {
  echo "Pictures are different, distance=$d\n";
}

Сжатие подписей для хранения в базе данных:

$compress_cvec1 = puzzle_compress_cvec($cvec1);
$compress_cvec2 = puzzle_compress_cvec($cvec2);


pHash


Вот и добрались до самого точного способа нахождения дубликатов — сравнение файлов через перцептивный хеш. Проверка на схожесть проводится путем подсчета количества отличающихся позиций между двумя хешами, это расстояние Хэмминга. Чем расстояние меньше — тем больше совпадение. Отличается от первого способа тем, что указывает не только на одинаковость/неодинаковость, но и на степень различия.
Этот метод рассчитан на поиск частичных или полных дубликатов, но также найдет незначительно отредактированные картинки – с измененной яркостью, цветовой гаммой и т.д. Подробнее об этом принципе можно прочитать в неплохом переводе.
Попробовать на деле можно через /инструмент/. Загрузка изображений через интерфейс и на выдаче результаты перцептивных хешей и показатель «одинаковости».
Мы сравнили бла-бла…

Комментарии ()


  1. GliX
    04.06.2015 15:13

    Мы сравнили бла-бла…
    Еще и раньше срока пост опубликовали.