我有超过10K个产品文件,问题是其中很多图片是重复的。
如果没有图片,会显示一个标准的“无图像”图片。
如何检测该图片是否为标准的“无图像”文件?
更新 该图片有不同的名称,但除此之外完全相同。
人们说可以用哈希算法,那么我应该怎么做呢?
im = cStringIO.StringIO(file.read())
img = im.open(im)
md5.md5(img)
我有超过10K个产品文件,问题是其中很多图片是重复的。
如果没有图片,会显示一个标准的“无图像”图片。
如何检测该图片是否为标准的“无图像”文件?
更新 该图片有不同的名称,但除此之外完全相同。
人们说可以用哈希算法,那么我应该怎么做呢?
im = cStringIO.StringIO(file.read())
img = im.open(im)
md5.md5(img)
顺便提一句,对于图像,我发现光栅数据的哈希比文件哈希更有效。
ImageMagick提供了可靠的方法来计算此类哈希值,并且有不同的Python绑定可用。它有助于检测具有不同无损压缩和不同元数据的相同图像。
使用示例:
>>> import PythonMagick
>>> img = PythonMagick.Image("image.png")
>>> img.signature()
'e11cfe58244d7cf98a79bfdc012857a9391249dca3aedfc0fde4528eed7f7ba7'
我之前写了一个脚本。首先,它会扫描所有文件,并在字典中记录它们的大小。最终得到:
images[some_size] = ['x/a.jpg', 'b/f.jpg', 'n/q.jpg']
images[some_other_size] = ['q/b.jpg']
然后,对于字典中有超过1个元素的每个键(图像大小),我会读取一定量的文件并进行哈希处理。类似于:
possible_dupes = [size for size in images if len(images[size]) > 1]
for size in possible_dupes:
hashes = defaultdict(list)
for fname in images[size]:
m = md5.new()
hashes[ m.update( file(fname,'rb').read(10000) ).digest() ] = fname
for k in hashes:
if len(hashes[k]) <= 1: continue
for fname in hashes[k][1:]:
os.remove(fname)
假设您所说的是相同的图像数据。
计算“无图像”图像的哈希值,并将其与其他图像的哈希值进行比较。如果哈希值相同,则为同一文件。
我在Fedora上安装PythonMagick时遇到了问题,但是另一个ImageMagick绑定库Wand可以正常工作。
from wand.image import Image
img = Image(filename="image.jpg")
print(img.signature)
请确保先安装好所有内容:
yum install python3-wand ImageMagick
set()
或dict()
中计算哈希值并进行比较的O(N)算法会更加高效。请注意,您不需要对整个文件进行哈希 - 前面的几KB大小的数据通常已经足够作为第一次检查。 - John La Rooy对它们进行散列。冲突是重复的(至少,数学上不可能它们不是同一个文件)。