Python 检查某个文件夹中是否有图像复制的最有效(比我的好)方法?

Python 检查某个文件夹中是否有图像复制的最有效(比我的好)方法?,python,python-3.x,image,numpy,Python,Python 3.x,Image,Numpy,我不确定我是否做得对。 我已经创建了multiply文件的multiply“copy”,它们在某种程度上应该是不同的(图像增强)。 现在,因为可能性对我不利,我想检查是否有任何创建的文件与任何其他创建的文件相等。要么是我的运气,要么是我把代码搞砸了。因为有很多文件,我无法手动检查它们。也许有一种比2更快的循环方式 我有以下代码 import sys import os import glob import numpy import time import datetime start_tim

我不确定我是否做得对。 我已经创建了multiply文件的multiply“copy”,它们在某种程度上应该是不同的(图像增强)。 现在,因为可能性对我不利,我想检查是否有任何创建的文件与任何其他创建的文件相等。要么是我的运气,要么是我把代码搞砸了。因为有很多文件,我无法手动检查它们。也许有一种比2更快的循环方式

我有以下代码

import sys
import os
import glob
import numpy
import time
import datetime


start_time = time.time()
print(datetime.datetime.now().time())

img_dir = sys.argv[1] 
data_path = os.path.join(img_dir,'*g')
files = glob.glob(data_path)
something_went_wrong = False

for f1 in files:
    for f2 in files:
        if f1 != f2:
            if open(f1,"rb").read() == open(f2,"rb").read():
                something_went_wrong = True
                print(f1)
                print(f2)
                print("---")

print(something_went_wrong)
print("--- %s seconds ---" % (time.time() - start_time))

试着按照建议使用散列。如果一个像素改变,散列也会改变

import hashlib
def hash_file(filename):
   # use sha1 or sha256 or other hashing algorithm
   h = hashlib.sha1()

   # open file and read it in chunked
   with open(filename,'rb') as file:
       chunk = 0
       while chunk != b'':
           chunk = file.read(1024)
           h.update(chunk)

   # return string
   return h.hexdigest()


它不受文件名或元数据的影响!将结果放在数据框中,这样很容易获得重复项。这种方法使用哈希函数与文件列表字典相结合,并计算每个元素出现的次数,这是对另一种方法的轻微扩展

您可能正在谈论不同文件夹中的重复文件名,这意味着我将以稍微不同的方式将初始的
文件列表
放在一起,但这是我如何解决此问题的基础(取决于
glob.glob
返回的内容)


如评论中所述,按大小分组可以节省时间:

import os
from collections import defaultdict
def fin_dup(dir):
    files=defaultdict(set)
    res=[]
    for fn in os.listdir(dir):
        if os.path.isfile(fn):
            files[os.stat(fn).st_size].add(fn) # groups files by size

    for size,s in sorted(files.items(),key=lambda x : x[0],reverse=True): #big first 
        while s:
            fn0=s.pop()
            s0={fn0}
            for fn in s:
                if open(fn0,'rb').read() == open(fn,'rb').read(): s0.add(fn)
            s -= s0
            if len(s0) > 1: res.append(s0)
    return res

此函数用不到1秒的时间扫描包含1000个文件的目录,并找到79个重复文件。仅对文件进行哈希运算需要10秒。

我可能会创建一个包含所有文件名的列表,并比较该列表和一组列表的长度。然后取列表中不在集合中的任何内容,使用
hashlib
对其进行散列,并比较f1和f2值。虽然看起来像是在同一个列表
文件中进行嵌套循环,但你会发现大量的“重复项”,它们实际上并不……我想,我的意思是显示相同的图片。例如,如果像素相同,则应将“出错的部分”设置为True。如果像素有点偏离,则不应将其设置为True。当前,布尔值从未设置为True。这就是为什么要问这个问题,因为我假设可能有些图像显示的是完全相同的图片(像素级),实际上,您可以读取所有图像并将它们放入一个
集合中,然后检查集合的大小。唯一的问题可能是,如果真的有很多图像,而且它们非常大,那么将它们同时放在内存中是一个问题。另一个选择是根本不编写任何代码,而是使用web上免费提供的众多文件副本查找工具之一。“如果你正在学习如何检测复制品,这是一回事,但是如果你只是想完成一项工作,不要重新发明轮子。”乔纳·毕肖普我想我找到了我想要的答案。该死的,我没想过:)多谢了,guyshash是一个很长的操作,不确定你是否再次赢得直接比较。你只需要一个循环来识别你的重复项。使用两个for循环,可以运行n^2次。如果你有1000个文件,你需要一百万个比较。你是对的。我想说的是,一般来说,复制品很少。您只需比较相同大小的文件。大多数情况下,最多有2个文件大小相同,直接比较更好。如果目录中的所有文件大小相同(可能是原始图像),则您的解决方案是好的。
import os
from collections import defaultdict
def fin_dup(dir):
    files=defaultdict(set)
    res=[]
    for fn in os.listdir(dir):
        if os.path.isfile(fn):
            files[os.stat(fn).st_size].add(fn) # groups files by size

    for size,s in sorted(files.items(),key=lambda x : x[0],reverse=True): #big first 
        while s:
            fn0=s.pop()
            s0={fn0}
            for fn in s:
                if open(fn0,'rb').read() == open(fn,'rb').read(): s0.add(fn)
            s -= s0
            if len(s0) > 1: res.append(s0)
    return res