在Java中识别具有相同内容的图像

不久之前,我花了一些时间寻找方法来确定两个图像是否相同才能回答这个问题 。 我现在面临一个稍微不同的问题:我手边有大约两千张图像,其中一些具有相同的内容,但是彼此的缩放/旋转版本(旋转总是90°的倍数),以及不同的压缩和图像格式(主要是jpg,一些png,没有别的)。 缩放不超过大约2:1。 我想做的是消除重复,同时保留最高质量的实例。 由于Java是我非常熟练的唯一语言,我需要使用Java。

对不同问题的回答提供了许多有用的链接,但看起来它们中的任何一个都不能在缩放/旋转时识别重复。

这个问题以及答案建议首先将所有图像缩放到非常小的尺寸(例如32 * 32或16 * 16),然后基本上进行一些散列,并基于散列进行比较。 这对我来说听起来很聪明,图像可以在比较之前预先排序,这将在排序之后成为O(n)问题。 但是,鉴于图像可能会旋转,我不知道如何处理它; 一种选择是手动浏览所有图像并决定旋转,因为它们所描绘的具有明确的方向(人眼可以非常容易地决定“向上”应该是哪种方式)。 如果可能的话,我想避免这样做。

是否有既定的方法/算法(链接提到SSIM)来处理这类问题,或者你们中的任何人都可以提出比上述更好的方法吗? 也许有人知道适合Java的Java库(在链接的问题中提到了OpenCV的Java包装器,然后是ImageJ,imgsclr)? 任何帮助表示赞赏。

我认为这个问题的一般答案需要一种无监督的机器学习方法,它可以生成局部不变特征 – 基本上是一种寻找不随缩放或旋转而变化的散列的奇特方法 – 然后运行聚类算法。 以下是一些可能相关的论文:

  • 聚类大型集合中的近重复图像
  • 一种基于PLSA模型的重复图像检测方法
  • 基于图像分析的高效图像复制检测 – 这里有很多东西,因为这是一些学生的整个博士论文

我认为dHash是你需要的东西。 您只需要改进dHash以考虑旋转,这意味着2000个图像将被视为8000个图像。

这几天我写了一个纯java库。 您可以使用目录路径(包括子目录)来提供它,它将使用您要删除的绝对路径列出列表中的重复图像。 或者,您也可以使用它来查找目录中的所有唯一图像。

它在内部使用了awt api,因此不能用于Android。 因为,imageIO在阅读很多新类型的图像时遇到了问题,我使用了内部使用的十二只猴子jar。

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

可以从https://github.com/srch07/Duplicate-Image-Finder-API/blob/master/archives/duplicate_image_finder_1.0.jar下载内部捆绑的依赖项jar。

api也可以在不同大小的图像中找到重复。