Warning
Данный проект устарел, его работоспособность не гарантирована в связи с прекращением его поддержки.
Этот проект разрабатывался как удобный инструментарий для оптимизации обучения нейронных сетей, основной задачей которого была ликвидация повторного обучения нейросетей при высокой степени схожести изображений, но после реализации основного функционала библиотека пополнилась удобной структурой и классами, позволяющими не только сравнивать изображения и датасеты по многим самым часто используемым метрикам и методам, но и удобно работать с изображениями и датасетами в любых других целях.
# Welcome to visdatcompy!img=Image(r"datasets\dataset\image.jpg")
dts=Dataset(r"datasets\dataset")
img.info()
dts.info()
> [V] ImageInformation:
> [$] Названиеизображения: image.jpg> [$] Разрешениеизображения: 6000x4000x3> [V] DatasetInformation:
> [%] Названиедатасета: dataset> [%] Количествоизображений: 322> [%] Путькдатасету: datasets\datasetОбучение нейросети занимает очень много времени. Сравнение датасетов позволит оценить их схожесть, а значит не обучать нейросеть заново при высоком сходстве. При работе с изображениями не было удобного инструмента для сравнения изображений по метаданным и метрикам.
Любой тип файла (звук, текст, изображение, видео) имеет свои стандарты метаданных. Для цифровых фотографий, в основном, используют:
- EXIF(Exchangeable Image File Format) — техническая информация о деталях съемки сделанная фотокамерой;
- XMP(eXtensible Metadata Platform) — стандарт, разработанный Adobe позволяющий включать любую информацию;
- Свойства файла — дополнительные параметры, являющиеся неотъемлемой частью фото.
При выстраивании логики сравнения было найдено оптимальное решение для отсеивания полных дубликатов с минимальной затратой времени - сравнение по exif-данным. Функционал для работы с exif-данными изображений в visdatcompy может быть использован как в личных целях пользователей, так и для нахождения дубликатов изображений.
Пример извлечения метаданных изображения:
# Создаём объект класса изображенияimg=Image(r"datasets\dataset\image.jpg")
# Извлекаем exif-данные в аттрибут exif_dataimg.get_exif_data()
# Выводим значение полученного аттрибута (словаря)print(img.exif_data)
>'ResolutionUnit': 2,
>'ExifOffset': 364,
>'Make': 'SONY',
>'Model': 'ILCE-6000',
>'Software': 'ILCE-6000 v2.00',
>'DateTime': '2017:06:11 11:39:36'
...Пример извлечения метаданных датасета:
# Создаём объект класса датасетdataset=Dataset(r"datasets\dataset")
# Извлекаем exif-данные в аттрибут exif_datadataset.get_exif_data()
# Выводим значение полученного аттрибута (pd.DataFrame)print(dataset.exif_data)
> ...Метрика - расстояние, определённое для любых двух элементов (точек) некоторого множества X. То есть это функция, которая возвращает расстояние между двумя объектами. Благодаря этому свойству мы можем расположить объекты от "идентичны" до "абсолютно разные".
| Метрика | Диапазон значений | Описание |
|---|---|---|
| PixToPix | True/False | Попиксельное сравнение двух изображений |
| MSE | [0; ∞) | Среднеквадратичная ошибка между изображениями |
| NRMSE | [0, 1] | Нормализованная среднеквадратическая ошибка |
| SSIM | [-1;1] | Структурное сходство изображений |
| PSNR | (0; ∞) | Отношение максимального значения сигнала к шуму |
| MAE | [0; ∞) | Средняя абсолютная ошибка между изображениями |
| NMI | [1;2] | Нормализованный показатель взаимной информации |
Tip
Pixel to pixel (pix2pix) не является полноправной метрикой, так как по сути своей это полное сравнение всех пикселей двух изображений между собой, однако для удобства был реализован в классе Metrics. Выходными данными этого метода является булево значение: True при полной схожести и False если есть различие. Его с лёгкостью заменяет сравнение по метаданным.
Пример сравнения двух датасетов по метрике:
# Создаём объекты двух датасетовdataset1=Dataset(r"datasets\first_dataset")
dataset2=Dataset(r"datasets\second_dataset")
# Создаём объект класса Metrics для работы с метрикамиmetrics=Metrics(dataset1, dataset2, r"results/metrics_results")
# Сохраняем результат сравнения двух датасетовmae_result=metrics.mae(echo=True, to_csv=True)
# Визуализируем результатmetrics.show(mae_result)Метод SIFT(Scale-Invariant feature transform — масштабно-инвариантная трансформация признаков) содержит детекторы для определения интересующих нас характерных точек на изображении и отбрасывании низкоконтрастных ключевых точек. Выходной величиной является представление соседней с характерной точкой области в виде вектора дескрипторов.
Пример работы с SIFT:
fromvisdatcompyimportDataset, FeatureExtractor# Создаём два объекта с датасетамиdataset1=Dataset("../datasets/cows")
dataset2=Dataset("../datasets/cows_duplicates")
# Создаём объект класса FeatureExtractor для работы с методом SIFT:fext=FeatureExtractor(dataset1, dataset2, "sift")
# Ищем схожие изображенияfext.find_similars()
print(fext.sift_similars)В результате получаем атрибут в виде словаря, где ключи - объекты изображений из первого датасета, а значения - объекты изображений из второго датасета, являющиеся схожими.
ORB(Oriented FAST and Rotated BRIEF) - Ориентированный алгоритм быстрого обнаружения особенностей и вращенных бинарных инвариантных характеристик.
Работа с ORB отличается от работы с SIFT только аргументом, передаваемым в функцию.
FAST(Features from Accelerated Segment Test) - Быстрый алгоритм обнаружения особенностей.
Работа с FAST отличается от работы с SIFT только аргументом, передаваемым в функцию.
Пример сравнения двух датасетов на основе хэшей:
# Создаём два объекта класса Datasetdataset1=Dataset(r"datasets\first_dataset")
dataset2=Dataset(r"datasets\second_dataset")
# Создаём объект класса HASH для сравнения двух датасетовhash=Hash(dataset1, dataset2)
# Находим схожие изображения и экспортируем результат в csv файлHash.find_similars("average", to_csv=True)| Характеристика | Описание |
|---|---|
| AverageHash | Рассчитывает хэш-значение на основе среднего значения пикселей, быстрый алгоритм хэширования изображений, но подходит только для простых случаев. |
| PHash | Улучшенная версия AverageHash, медленнее чем AverageHash, но может адаптироваться к более широкому спектру ситуаций. |
| MarrHildrethHash | Значение хэша рассчитывается на основе оператора граней Марра-Хилдрета, что является самым медленным, но более дискриминативным методом. |
| RadialVarianceHash | Рассчитывает хэш-значение на основе преобразования Радона. |
| BlockMeanHash | Рассчитывает хэш-значение на основе среднего значения блоков, представленного в том же статье, что и MarrHildrethHash. |
| ColorMomentHash | Рассчитывает хэш-значение на основе моментов цвета, представленного в той же статье, что и RadialVarianceHash. |
Для объединения всех методов поиска дубликатов и схожих изображений мы реализовали весь главный функционал в одном классе VisDatCompare:
# Создаём объекты класса Datasetdataset1=Dataset("datasets/drone")
dataset2=Dataset("datasets/drone_duplicates")
# Создаём объект класса VisDatCompare поиска дублей и схожестейcompy=VisDatCompare(dataset1, dataset2)
# Ищем дубликаты изображений методом MSE:compy.duplicates_finder.find_metrics_duplicates("mse")
# Удаляем дубликатыcompy.duplicates_finder.clear_duplicates()
# Ищем схожие изображения с помощью SIFT:compy.similars_finder.find_features_similars("sift")
# Удаляем схожие изображенияcompy.similars_finder.clear_similars()Таким образом буквально в несколько строк мы можем реализовать оптимальную логику:
- Быстро отсеять дубликаты по exif-характеристикам
- Убрать не несущие в себе exif-данные, дубликаты изображений методом Pixel to Pixel или с помощью метрик.
- Определить уже среди оставшихся изображений схожие по нескольким методам и также их удалить при необходимости.
> pip install visdatcompyПереходим в нужную директорию и клонируем репозиторий:
> git clone https://github.com/cloudsucker/visdatcompy.gitПеред работой с библиотекой рекомендуется настроить виртуальное окружение для последующей работы в нём.
1. Переходим в корень проекта:
> cd visdatcompy2. Создаём виртуальное окружение:
> python -m venv .venv3. Активируем его:
> .venv\Scripts\activate.batПеред началом работы с библиотекой необходимо также установить вспомогательные библиотеки из файла зависимостей:
> pip install -r requirements.txt Последним этапом необходимо установить библиотеку в режиме редактирования:
> pip install -e .По всем вопросам: ferjenkill@gmail.com



