比较图像以查找重复项

spa*_*ron 6 java sha1 image-processing

我在一个文件夹中有一些(38000)图片/视频文件.其中大约40%是重复的,我试图摆脱它.我的问题是,如何判断2个文件是否相同?到目前为止,我尝试使用文件的SHA1但事实证明许多重复文件有不同的哈希值.这是我使用的代码:

public static String getHash(File doc) {
    MessageDigest md = null;
    try {
        md = MessageDigest.getInstance("SHA1");
        FileInputStream inStream = new FileInputStream(doc);
        DigestInputStream dis = new DigestInputStream(inStream, md);
        BufferedInputStream bis = new BufferedInputStream(dis);
        while (true) {
            int b = bis.read();
            if (b == -1)
                break;
        }

        inStream.close();
        dis.close();
        bis.close();
    } catch (NoSuchAlgorithmException | IOException e) {
        e.printStackTrace();
    }

    BigInteger bi = new BigInteger(md.digest());

    return bi.toString(16);
}
Run Code Online (Sandbox Code Playgroud)

我能以任何方式修改吗?或者我必须使用不同的方法吗?

小智 6

如上所述,重复检测可以基于散列.但是,如果您希望接近重复检测,这意味着您要搜索的图像基本上显示相同的内容,但已经缩放,旋转等,您可能需要基于内容的图像检索方法.有LIRE(https://code.google.com/p/lire/),这是一个Java库,您可以在下载部分找到"SimpleApplication".那你可以做的是

  1. 索引第一张图片
  2. 转到下一个图像我
  3. 在索引中搜索I.
  4. 如果有得分低于阈值的结果,则将其标记为重复
  5. 索引I.
  6. 转到(2)

我的学生做了它,它运作良好,但我没有手头的源代码.但请放心,它只是几行,简单的应用程序将帮助您入门.


MvG*_*MvG 1

您可以使用imagemagick 等将文件转换具有规范表示形式和尽可能少的元数据的格式。我想我会使用PNM。所以尝试这样的事情:

convert input.png pnm:- | md5sum -
Run Code Online (Sandbox Code Playgroud)

如果这确实对之前比较不同的两个文件产生相同的结果,那么元数据实际上是问题的根源,您可以使用像这样的命令行方法,或者更新代码来读取图像并计算哈希值来自原始未压缩数据。

另一方面,如果不同的文件仍然比较不同,那么您对实际图像数据进行了一些更改。一个可能的原因可能是添加或删除了 Alpha 通道,特别是当您在此处处理 PNG 时。另一方面,使用 JPEG,您可能会先未压缩图像,然后再次重新压缩,这将导致轻微的修改和数据丢失。JPEG 本质上是一种有损编解码器,任何两个图像都可能会有所不同,除非它们是使用相同的应用程序(或库)、相同的设置和相同的输入数据创建的。在这种情况下,您需要执行模糊图像匹配。像Geeqie这样的工具可以执行此类操作。如果您想自己做这件事,那么您将需要做很多工作,并且应该提前做一些研究。