Идентификация изображений с одним контентом в Java

Некоторое время назад я потратил некоторое время на поиск способов определить, идентичны ли два изображения, чтобы ответить на этот вопрос. Теперь я сталкиваюсь с немного другой проблемой: у меня есть около двух тысяч изображений под рукой, некоторые из которых имеют одинаковое содержимое, но имеют масштабированные/повернутые версии друг друга (вращения всегда кратно 90 °), а также проблема различные сжатия и форматы изображений (в основном jpg, некоторые png, ничего больше). Масштабирование не выходит за пределы примерно 2: 1. То, что я хотел бы сделать, это исключить дубликаты, сохранив при этом экземпляр самого высокого качества. Поскольку Java является единственным языком, на котором я достаточно разбираюсь, мне нужно использовать Java.

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

Этот вопрос вместе с ответами предлагает сначала масштабировать все изображения до очень небольшого размера (скажем, 32 * 32 или 16 * 16), а затем в основном делать хэширование, и сравнения, основанные на хеше. Это звучит достаточно разумно для меня, изображения могут быть предварительно отсортированы перед сравнением, что после сортировки будет проблемой O (n). Однако, учитывая, что изображения могут быть повернуты, я не уверен, как с этим бороться; одним из вариантов было бы вручную пройти все изображения и принять решение о ротации, учитывая, что то, что они изображают, имеет четкую ориентацию (человеческий глаз может очень легко решить, каким образом "вверх" должен быть). Если возможно, я бы хотел этого избежать.

Существуют ли установленные методы/алгоритмы (ссылки ссылаются на SSIM), чтобы справиться с такими проблемами, или может кто-нибудь из вас придумать лучшие способы, чем описано выше? Может быть, кто-то знает библиотеки для Java, которые хорошо подходят для задачи (в связанных вопросах есть упоминание о оболочке Java для OpenCV, а затем ImageJ, imgsclr)? Любая помощь приветствуется.

Ответ 1

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

Ответ 2

Ну, я думаю, что dHash - это то, что вам нужно. Вам просто нужно улучшить dHash, чтобы принять во внимание поворот, то есть 2000 изображений будут считаться 8000 изображений.

Я написал чистую библиотеку java только за эти несколько дней назад. Вы можете подать его с помощью пути к каталогу (включая подкаталог), и он отобразит дубликаты изображений в списке с абсолютным путем, который вы хотите удалить. Кроме того, вы можете использовать его для поиска всех уникальных изображений в каталоге.

Он использовал awt api внутренне, поэтому его нельзя использовать для Android. Поскольку у imageIO есть проблемы с чтением многих новых типов изображений, я использую двенадцать банд обезьян, которые используются внутри.

https://github.com/srch07/Duplicate-Image-Finder-API

Jar с зависимостями, входящими внутри, можно загрузить с https://github.com/srch07/Duplicate-Image-Finder-API/blob/master/archives/duplicate_image_finder_1.0.jar

Апи может найти дубликаты среди изображений разных размеров.