Сравнение изображений через хэш

Обновлено: 02.07.2024

Не могу найти работающие функции для получения хэшей, всё либо устарело, либо было удалено ранее.

Или же есть ещё какие либо способы сравнить изображения через встроенные функции OpenCv?

__________________
Помощь в написании контрольных, курсовых и дипломных работ здесь

Сравнение двух изображений с IP-камеры
Доброго времени суток! задача стоит в определении изменения положения IP-камеры, фокусировки и.

Сравнение двух изображений
Есть два изображения (скриншоты которые которые делает питон), конкретнее мини-карта, нужно найти.

Сравнение двух изображений
Подскажите пожалуйста как сравнить два объекта Image на предмет того, содержат они разное.

Сравнение двух изображений на идентичность
Привет всем. Есть такой вопрос можно ли сравнивать отличие двух изображений? Если да как? Условия.

Так,ага, спасибо, только вот я сижу на этой статье уже вторые сутки потому что файла img_hash у меня нет.

Я уже подумал, что его удалили, и забыли удалить с документации. Антивирус был отключен, в карантине файла нет.

Добавлено через 27 минут
Если бы кто нибудь сейчас перешёл по пути установки библиотеки в include/opencv2 и сказал бы, на месте ли у вас файл img_hash.hpp вы бы мне очень помогли. Ибо я не могу понять, системная ли это проблема, либо же его действительно удалили.

YanShun, Ну вообще то ты можешь сравнить скажем по пиксельно. способов много суть одна Если бы кто нибудь сейчас перешёл по пути установки библиотеки в include/opencv2 и сказал бы, на месте ли у вас файл img_hash.hpp вы бы мне очень помогли. Если в сборке отсутствуют упомянутые инклюды, можно попробовать подключить cv - пространства имен через базовый img_hash_base.hpp не включая

tityanos, Уже пробовал сравнение попиксельно, но оно не работает в связи с техническими причинами в самом приложении.

Decosa, спасибо, но я уже использую другой метод, а стандартный image_hash был удалён из новых версий OpenCv

Добавлено через 2 часа 50 минут
Итак, вот готовый вариант сравнения двух практически идентичных изображений (того же формата, и размера).

Добавлено через 4 минуты
Ах да, к слову, что я сделал.

!)Получил изображения
2)Проверил, не пустые ли они (image.empty())
3) Создал матрицу для хранения результата result
4) Вызвал функцию absdiff, которая вычитала из первой матрицы(изображения) вторую матрицу, и возвращала результат в матрицу result.
5) И дальше с помощью countNonZero(result) мы проверили, если изображения идентичны, то result должна была равняться 0, что означало, что изображения равны.


Нехватка памяти, попиксельное сравнение двух изображений
Добрый день ув. Программисты. Есть код сравнения двух изображений по пиксельно: procedure.

Сравнение хэш-кодов
Доброго времени суток, делаю работу про хэширование, хэш-функции и.т.д Хотел бы подкрепить.


Сравнение двух объектов через конструктор с одним аргументом
class Int < private: unsigned int integer; public: inline int get_int()const

Сравнение элементов двух коллекций через Stream API
Приветствую, комрады! Есть класс Person, содержащий HashMap с данными на человека: class.

картинка номер 1
картинка номер 2

Сравнение картинок, которые могут отличаться размером (яркостью, контрастностью и т.п.), можно через перцептивные хэш-алгоритмы.

Перцептивные хэши можно сравнивать между собой и делать вывод о степени различия двух наборов данных.

По этому теме есть статья на хабрахабре. Также я находил реализацию этого алгоритма на с++. Для java уверен либо есть алгоритмы, либо можно написать, т.к. там нет ничего запредельного.

Тут я опишу общий алгоритм, приведя из статьи на хабре:

  1. Уменьшить размер. Самый быстрый способ избавиться от высоких частот — уменьшить изображение. В данном случае мы уменьшаем его до 8х8, так что общее число пикселей составляет 64. Можно не заботиться о пропорциях, просто загоняйте его в квадрат восемь на восемь. Таким образом, хэш будет соответствовать всем вариантам изображения, независимо от размера и соотношения сторон.

  2. Убрать цвет. Маленькое изображение переводится в градации серого, так что хэш уменьшается втрое: с 64 пикселей (64 значения красного, 64 зелёного и 64 синего) всего до 64 значений цвета.

  3. Найти среднее. Вычислите среднее значение для всех 64 цветов.

  4. Цепочка битов. Это самое забавное: для каждого цвета вы получаете 1 или 0 в зависимости от того, он больше или меньше среднего.

  5. Постройте хэш. Переведите 64 отдельных бита в одно 64-битное значение. Порядок не имеет значения, если он сохраняется постоянным (я записываю биты слева направо, сверху вниз).

Итого, чтобы сравнить две картинки:

  • Нужно найти перцептивные хэши обеих картинок.
  • С помощью расстояния Хэмминга определить степень различия хэшей и на основе различия определить их схожесть.

PS.

Для python есть библиотека для сравнения картинок imagehash. Я с нею игрался и могу предоставить два примера:

Консольный (поиск картинок в заданной папке и вывод похожих картинок)

Оконный (для выбранной картинки было найдено 3 похожих картинки, они были выделены рамкой и помещены в список ниже), скриншот:


авг 29, 2016 | 9 комментариев

Быстрое сравнение изображений на PHP через hash изображения

Иногда возникает потребность определить, являются ли два файла изображений одинаковыми, или очень похожими (когда одно из них было сильнее сжато, сохранено в другом формате файла, или размер его был изменён).
Это может понадобиться в следующих случаях:

  • У вас на сайте есть большая база изображений, и вы хотите найти в ней дубликаты (очень похожие друг на друга) с целью удаления.
  • На вашем сайте есть база изображений, и вы, при загрузке нового изображения, хотите проверить, нет ли уже такого
  • Вы хотите реализовать поиск по изображениям, то есть, если вы хотите выбрать из базы изображение, название которого не помните, но у вас есть его файл, вы можете загрузить этот файл и найти по нему уже существующий, и выбрать найденное

Долгие поиски в Интернете, не дали мне подходящего алгоритма, поэтому я создал свой.

Принцип действия

Вот как она генерируется:

Выбор параметров:

Для хэша нужно задать 2 параметра: размер и детализация.

Далее, исходное изображение с помощью функции библиотеки gd2 imagecopyresampled уменьшается до квадратного изображения со стороной $hashSizeRoot. Неважно, какие пропорции у исходного изображения, в результате всё равно получится квадрат.

Например, из такого вот изображения:

Получается вот такое:

(увеличено в 15 раз для наглядности)

Упрощение информации о цветности

Необходимо снизить количество цветов так, чтобы каждый пиксел уменьшенного изображения укладывался в 1 байт.
Изначально заданным является параметр $hashDetalization, он, как это уже упоминалось, определяет максимальное количество значений на каждый цветовой канал.

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

Как работает функция $colorSimplify:

Сохранение хэша

Сравнение хэша

Сравнивать хэши можно на точное равенство (то есть просто $hash1 == $hash2), а можно на приблизительное, которое несколько медленнее, но позволяет определять в качестве схожих более изменённые изображения.

При сравнивании на приблизительное равенство выбирается процент соответствия, различия менее которого считаются несущественными.

Приблизительное сравнение

/** * Сравнить два хэша изображений * @param string $hash1 хэш первого изображения в формате base64 * @param string $hash2 хэш второго изображения в таком же формате * @param float $epsilon Максимальная относительная ошибка. 1 это 100%, 0.5 это 50% и так далее. * @param boolean $error Ссылка на переменную, в которую будет записана величина ошибки (число от 0 до 1) * @param boolean $alreadyDecoded Флаг, указывающий, что переданные хэши уже декодированы из base64 * @return boolean возвращает true/false в зависимости от того, соответствуют ли друг другу хэши */ function compareImageHashes($hash1, $hash2, $epsilon = 0.01, &$error = 0, $alreadyDecoded = false) < $error = 1; if ($epsilon == 0) < return $hash1 == $hash2; >else < if ($hash1 == $hash2) return true; if (!$alreadyDecoded) < $h1 = base64_decode($hash1); $h2 = base64_decode($hash2); >else < $h1 = $hash1; $h2 = $hash2; >if (strlen($h1) != strlen($h2)) return false; $l = strlen($h1); $error = 0; $bytes1 = unpack("C*", $h1); $bytes2 = unpack("C*", $h2); for ($i=0;$i<$l;$i++) < $b1 = $bytes1[$i+1]; $b2 = $bytes2[$i+1]; if ($b1 != $b2) < $delta = abs($b1 - $b2); $mid = ($b1 + $b2) / 2; if ($delta > 0) < $e = $delta / $mid; $error += $e / $l; if ($error > $epsilon) return false; >> > return $error <= $epsilon; > >

Где взять и как пользоваться

Вычислим хэш изображения, лежащего в файле:

<?php require_once "ImageHash.php"; $ih = new ImageHash(); $hash = $ih->createHashFromFile("./test.jpg");

Вычислим хэш двух изображений и сравним их:

<?php require_once "ImageHash.php"; $ih = new ImageHash(); $hash1 = $ih->createHashFromFile("./test1.jpg"); $hash2 = $ih->createHashFromFile("./test2.jpg"); $isEqual = ($hash1 == $hash2) $isNearEqual = $ih->compareImageHashes($hash1, $hash2, 0.05); echo "Хэши изображений равны?:" . ($isEqual ? "Да" : "Нет"); echo "Хэши изображений равны с точностью до 5%?:" . ($isNearEqual ? "Да" : "Нет");

Вычислим хэш изображения из объекта image, с большей детализацией

$ih = new ImageHash(); $image = imagefromjpeg("./file.jpg"); $hash = $ih->createHash($image, 10, 6);

9 комментариев

Огромное человеческое спасибо!

Огромное человеческое пожалуйста

Благодарю, полезный скрипт. Задействовал у себя для обновления изображений если оно изменилось. Благодарю!

Также нашёл ошибку, выше в примере указано:

$isNearEqual = $ih->compare($hash1, $hash2, 0.05);

В файле imagehash написана функция compareImageHashes:

$isNearEqual = $ih->compareImageHashes($hash1, $hash2, 0.10);

Спасибо за комментарий, действительно похоже на ошибку

Мне кажется, что в методе упрощения тоже есть ошибка.
В этой строчке:
$simpleColor = ($simpleR + $simpleG * $colorsPerChannel + $simpleB * $colorsPerChannel * $colorsPerChannel);
Разве не должно быть так:
$simpleColor = ($simpleR * $colorsPerChannel + $simpleG * $colorsPerChannel + $simpleB * $colorsPerChannel );

Спасибо за столь подробное обьяснение, думаю теперь я понял)

Спасибо за отличную публикацию.
Скажите пожалуйста функция gd2 imagecopyresampled это стандартное масштабирование без сохранения пропорций, или это какое-то специфическое масштабирование?

Также если есть время/возможность набросать пример как на вход подавать не с файла, а например POST запросом, передавая картинку в base64.

Что касается передачи файла на вход пост-запросом, это делается легко.


В этом посте мы пытаемся достичь вышеуказанного результата, то есть, учитывая изображение, мы должны быть в состоянии найти похожие изображения изБаза данных Caltech-101, В этом посте рассказывается о том, как я это сделал. Вся база кода для репликации проекта находится в моемGitHub репозиторий, Процесс достижения вышеуказанного результата можно разбить на следующие несколько шагов:

  1. Передача обучения по модели ResNet-34 (обученной в ImageNet) для обнаружения 101 класса вНабор данных Caltech-101с помощьюFastAIа такжеPytorch,
  2. Возьмите выходные данные второго последнего полностью подключенного слоя из обученной модели ResNet 34, чтобы получить вложение для всех 9,144 изображений Caltech-101.
  3. Используйте локально-чувствительное хеширование, чтобы создать LSH-хеширование для встраивания нашего изображения, что позволяет быстро приближенно искать ближайшего соседа
  4. Затем по заданному изображению мы можем преобразовать его во встраивание изображения, используя нашу обученную модель, а затем выполнить поиск похожих изображений, используя Приблизительный ближайший сосед в наборе данных Caltech-101.

Как я упоминал выше, для этого проекта моя цель состоит в том, чтобы запросить любое изображение и найти семантически похожее изображение вБаза данных Caltech-101, Эта база данных содержит 9,144 изображений, разделенных на 101 категории. В каждой категории около 50–800 изображений.


Первое упражнение в нашем проекте - создать сеть глубокого обучения, которая может точно классифицировать эти категории. Для этой задачи мы будем использовать предварительно обученную сеть ResNet 34, которая обучена работе с базой данных ImageNet, и перенесем ее на обучение для классификации 101 категории базы данных Caltech-101 с использованием Pytorch 1.0 и библиотеки FastAI. Как я уже писал о том, как сделать перенос обучения с любым данным набором в моемпредыдущий блогЯ просто собираюсь изложить процесс в этом блоге. Вы можете обратиться кэтот блокнотчтобы найти код, чтобы сделать то же самое. Ниже приведены шаги, чтобы выполнить трансферное обучение для классификации изображений Caltech-101 -

  1. Загрузка данных с использованием загрузчиков наборов данных Pytorch с использованием библиотеки FastAI
  2. Возьмите предварительно обученную сеть, в данном случае ResNet 34, и удалите последние полностью подключенные слои.
  3. Добавьте новые полностью связанные слои в конце сети и обучите только те слои, используя изображение Caltech-101, сохраняя все остальные слои замороженными
  4. Обучите всю сеть, разморозив все слои

Теперь, когда у нас есть предварительно обученная сеть, нам нужно извлечь вложения из этой сети для всех наших изображений Caltech-101. Встраивание - это не что иное, как представление объекта в N-мерном векторе. В этом случае встраивание изображения является представлением изображения в N-измерении. Основная идея заключается в том, что чем ближе данное изображение к другому изображению, их вложение также будет сходным и близким в пространственном измерении.

Визуализация встраивания изображений. Кредит -Блог

Вы можете увидеть на изображении выше, взятом изэтот блогэто вложение изображения является пространственным представлением изображения в векторизованной форме, где сходные изображения также близки в пространственном измерении.

Мы можем получить вложения изображений из ResNet-34, взяв выходные данные его второго последнего полностью связанного слоя, который имеет размерность 512. Чтобы сохранить промежуточные вычисления в модели глубокого обучения в Pytorch для проверки или в нашем случае для извлечения вложений, мы использовать Pytorch Hooks. Крючки могут быть двух типов - вперед и назад. Прямые перехватчики используются для сохранения информации, передаваемой вперед в сети, чтобы сделать вывод, в то время как обратные перехватчики используются для сбора информации о градиентах во время обратного распространения. В нашем случае нам нужен вывод наших вторых последних Полностью связанных слоев на этапе вывода, что означает, что нам нужно использовать прямой хук. Давайте посмотрим на код для создания хука (также в разделе «Извлечение функции» моегоблокнот) -

Приведенный выше код - это все, что вам нужно для создания хука Pytorch. Класс SaveFeatures вызываетregister_forward_hookфункция отмодуль torch.nnи с учетом любого уровня модели он сохранит промежуточные вычисления в массиве, который можно получить с помощью функций SaveFeatures.features. Давайте посмотрим код для использования этого класса -

Строка 1–2: вызывает класс SaveFeatures, используя в качестве входных данных ссылку на слой модели на выход второго последнего полностью связанного слоя.

Строка 4–6: Передача данных Caltech-101 для получения их прогнозов. Обратите внимание, что нас не интересует сохранение прогнозов, и поэтому мы использовали «_». В этом случае промежуточный вывод вторых последних слоев сохраняется в переменной с именем «sf», которая является экземпляром класса SaveFeatures.

Строка 8–10: создание словаря python, где путь к изображению является ключом, а вложения изображения - это значение

Теперь у нас есть встраивание представления каждого изображения в Caltech-101 в нашем словаре.

Мы можем использовать наши недавно сгенерированные вложения изображений Caltech 101 и получить новое изображение, преобразовать его во встраивание, чтобы вычислить расстояние между новым изображением и всей базой данных Caltech 101, чтобы найти похожие изображения. Этот процесс по своей природе дорогостоящий в вычислительном отношении, и, поскольку новое вложение изображения необходимо сравнить со всем встраиванием изображения 9K + в базу данных Caltech 101, чтобы найти наиболее похожее изображение (ближайший сосед), которое в обозначении сложности вычислений является проблемой O (N²) и будет занимать экспоненциально больше времени для извлечения похожих изображений по мере увеличения количества изображений.

Чтобы решить эту проблему, мы будем использовать локально-чувствительное хеширование (LSH), которое является приближенным алгоритмом ближайшего соседа, который уменьшает вычислительную сложность до O (log N).Этот блогобъясняет LSH в хороших деталях с точки зрения сложности времени и реализации. Короче говоря, LSH генерирует хэш-значение для встраивания изображений, сохраняя при этом пространственность данных; особенно; элементы данных, которые похожи в высоком измерении, будут иметь более высокую вероятность получения того же значения хеш-функции.

Ниже приведены шаги о том, как LSH преобразует вложение в хэш размера K-

  1. Генерация K случайных гиперплоскостей в размерности вложения
  2. Проверьте, находится ли конкретное вложение над или под гиперплоскостью, и назначьте 1/0
  3. Выполните шаг 2 для каждой K гиперплоскостей, чтобы получить хеш-значение

Давайте теперь посмотрим, как LSH будет выполнять запрос ANN. Учитывая вложение нового изображения, мы будем использовать LSH, чтобы создать хеш для данного изображения, а затем сравним расстояние от встраивания изображений из набора данных Caltech-101, который имеет такое же значение хеш-функции. Таким образом, вместо поиска сходства по всей базе данных Caltech-101, мы будем выполнять поиск сходства только с подмножеством изображений, которые имеют одинаковое значение хеш-функции с входным изображением. Для нашего проекта мы используемlshash3пакет для приблизительного поиска ближайшего соседа. Давайте посмотрим на код, чтобы сделать то же самое (вы можете найти код в разделе «Использование хеширования с учетом локальных особенностей для поиска похожих изображений» моегоблокнот) -

Приведенный выше код берет словарь встраивания изображений и преобразует его в таблицу LSH. Чтобы запросить таблицу LSH, мы можем использовать код ниже -

Теперь у нас есть созданная таблица LSH. Давайте напишем скрипт, который может принимать URL-адрес изображения и предоставлять нам N (определенных пользователем) похожих изображений из базы данных CalTech 101. Код для этой части на моемGithub здесь,


Скрипт выполняет следующую задачу -

  1. Загрузите таблицу LSH и нашу модель ResNet 34 (функция load_model)
  2. Возьмите URL-адрес изображения из звонка пользователя и загрузите изображение (функция download_img_from_url)
  3. Передайте изображение из ResNet-34, чтобы получить вложение изображения 512 размеров (функция image_to_vec)
  4. Запросите его с помощью таблицы LSH, чтобы найти N (пользовательских) похожих изображений и их путь (функция get_simil_images)
  5. Вернуть вывод по желаемому выходному пути, при желании отобразить его с помощью Open CV (функция get_s Similar_images)

Мы можем использовать аналогичную концепцию в различных приложениях, таких как поиск похожих изображений в нашей фотогалерее, рекомендации по элементам для похожих элементов, поиск по изображениям в Интернете, поиск почти дублированных изображений и т. Д.

Резюме (TL; DR),

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

Читайте также: