为什么我的 Python 脚本被杀死,它用 Pillow 打开许多图像文件
Why is my Python script being killed that opens many Image files with Pillow
我有一个 python 脚本,它使用 Pillow 打开文件夹中的所有 png/jpg/jpeg 文件,复制它们的一些元数据(文件名、大小、宽度、高度、像素、大小、等)放入一个新对象并将该对象放入一个名为 imageMetaData 的列表中。然后我遍历该列表以将每个图像与其他图像进行比较以尝试删除重复图像(我已经积累了大量重复图像到我的 6000 张图像中至少有 1500 张可能是重复的)
使用小尺寸的图像(~1500 是我成功完成的最大图像)它工作正常!但是当尝试 运行 在我有 6100 个文件的文件夹上时,它没有成功创建 imageMetaData 列表并实际打印:
zsh: killed python3 remove-duplicates.py
我已经调查过了,似乎 运行 内存不足。但似乎我的 RAM 应该足以容纳 ~6000 个对象的列表,其中每个对象有大约 8 个字段。
我的函数如下:
from PIL import Image
from os import listdir
mypath = 'my-path-to-folder/remove-dupes/'
initialLocation = 'my-folder-of-photos'
directoryList = listdir(mypath + initialLocation)
def loadObjects():
myObjects = []
if len(directoryList) > 1:
for x in range(len(directoryList)):
if ('jp' in directoryList[x].lower() or 'png' in directoryList[x].lower()):
i = Image.open(mypath + initialLocation + '/' + directoryList[x])
width, height = i.size
pixels = i.load()
i.close()
myObjects.append({
'name': directoryList[x],
'width': width,
'height': height,
'pixels': pixels,
'size': os.stat(mypath + initialLocation + '/' + directoryList[x]).st_size,
'biggest': directoryList[x],
'index': x
})
return myObjects
如图所示,图像已打开、加载和关闭(正确吗?)所以我认为我没有留下任何东西。关于为什么它被杀死或者可能如何获得更多关于它为什么被杀死的细节的任何想法?
虽然它看起来不太漂亮,但我确实使用了 Noah 的建议,通过使用图像的高度和宽度 selecting 20 像素来减少将每个图像的整个像素阵列推入我的新对象。不幸的是,即使像素数组应该相同,使用 hash(pixels) 似乎也会返回一个唯一值?在尝试删除此逻辑并使用哈希值之前,需要研究为什么会这样。
def getRandomPixels(pixels, width, height):
randomPixels = []
randomPixels.append(pixels[0,0])
randomPixels.append(pixels[width - 1, height - 1])
randomPixels.append(pixels[0, height - 1])
randomPixels.append(pixels[width - 1, 0])
randomPixels.append(pixels[width/2, height/2])
randomPixels.append(pixels[0, height/2])
randomPixels.append(pixels[width/2, 0])
randomPixels.append(pixels[width - 1, height/2])
randomPixels.append(pixels[width/2, height - 1])
randomPixels.append(pixels[width/4, height/4])
randomPixels.append(pixels[0, height/4])
randomPixels.append(pixels[width/4, 0])
randomPixels.append(pixels[width - 1, height/4])
randomPixels.append(pixels[width/4, height - 1])
randomPixels.append(pixels[width/8, height/8])
randomPixels.append(pixels[0, height/8])
randomPixels.append(pixels[width/8, 0])
randomPixels.append(pixels[width - 1, height/8])
randomPixels.append(pixels[width/8, height - 1])
randomPixels.append(pixels[width/2, height/8])
return randomPixels
我选择 select 这样的像素是因为文件夹中的图像可能有不同的尺寸,这确保了 1024 x 2048 的图片总是会通过查看将自己与另一张相同尺寸的图片进行比较在相同的像素。它也 select 来自图片中相距较远且不太可能相似的部分,除非图片是重复的。
使用这种新方法,我能够 运行 通过 4975 张图像并在 618 秒内加载它们,然后检查重复项只用了 61 秒,因为我之前使用的像素阵列 运行宁可变成 20x20 而不是高 x 宽!谢谢诺亚!
我有一个 python 脚本,它使用 Pillow 打开文件夹中的所有 png/jpg/jpeg 文件,复制它们的一些元数据(文件名、大小、宽度、高度、像素、大小、等)放入一个新对象并将该对象放入一个名为 imageMetaData 的列表中。然后我遍历该列表以将每个图像与其他图像进行比较以尝试删除重复图像(我已经积累了大量重复图像到我的 6000 张图像中至少有 1500 张可能是重复的)
使用小尺寸的图像(~1500 是我成功完成的最大图像)它工作正常!但是当尝试 运行 在我有 6100 个文件的文件夹上时,它没有成功创建 imageMetaData 列表并实际打印:
zsh: killed python3 remove-duplicates.py
我已经调查过了,似乎 运行 内存不足。但似乎我的 RAM 应该足以容纳 ~6000 个对象的列表,其中每个对象有大约 8 个字段。
我的函数如下:
from PIL import Image
from os import listdir
mypath = 'my-path-to-folder/remove-dupes/'
initialLocation = 'my-folder-of-photos'
directoryList = listdir(mypath + initialLocation)
def loadObjects():
myObjects = []
if len(directoryList) > 1:
for x in range(len(directoryList)):
if ('jp' in directoryList[x].lower() or 'png' in directoryList[x].lower()):
i = Image.open(mypath + initialLocation + '/' + directoryList[x])
width, height = i.size
pixels = i.load()
i.close()
myObjects.append({
'name': directoryList[x],
'width': width,
'height': height,
'pixels': pixels,
'size': os.stat(mypath + initialLocation + '/' + directoryList[x]).st_size,
'biggest': directoryList[x],
'index': x
})
return myObjects
如图所示,图像已打开、加载和关闭(正确吗?)所以我认为我没有留下任何东西。关于为什么它被杀死或者可能如何获得更多关于它为什么被杀死的细节的任何想法?
虽然它看起来不太漂亮,但我确实使用了 Noah 的建议,通过使用图像的高度和宽度 selecting 20 像素来减少将每个图像的整个像素阵列推入我的新对象。不幸的是,即使像素数组应该相同,使用 hash(pixels) 似乎也会返回一个唯一值?在尝试删除此逻辑并使用哈希值之前,需要研究为什么会这样。
def getRandomPixels(pixels, width, height):
randomPixels = []
randomPixels.append(pixels[0,0])
randomPixels.append(pixels[width - 1, height - 1])
randomPixels.append(pixels[0, height - 1])
randomPixels.append(pixels[width - 1, 0])
randomPixels.append(pixels[width/2, height/2])
randomPixels.append(pixels[0, height/2])
randomPixels.append(pixels[width/2, 0])
randomPixels.append(pixels[width - 1, height/2])
randomPixels.append(pixels[width/2, height - 1])
randomPixels.append(pixels[width/4, height/4])
randomPixels.append(pixels[0, height/4])
randomPixels.append(pixels[width/4, 0])
randomPixels.append(pixels[width - 1, height/4])
randomPixels.append(pixels[width/4, height - 1])
randomPixels.append(pixels[width/8, height/8])
randomPixels.append(pixels[0, height/8])
randomPixels.append(pixels[width/8, 0])
randomPixels.append(pixels[width - 1, height/8])
randomPixels.append(pixels[width/8, height - 1])
randomPixels.append(pixels[width/2, height/8])
return randomPixels
我选择 select 这样的像素是因为文件夹中的图像可能有不同的尺寸,这确保了 1024 x 2048 的图片总是会通过查看将自己与另一张相同尺寸的图片进行比较在相同的像素。它也 select 来自图片中相距较远且不太可能相似的部分,除非图片是重复的。
使用这种新方法,我能够 运行 通过 4975 张图像并在 618 秒内加载它们,然后检查重复项只用了 61 秒,因为我之前使用的像素阵列 运行宁可变成 20x20 而不是高 x 宽!谢谢诺亚!