我有两个目录,每个目录包含大约50,000张图像,它们大多是240x180大小。
我想pickle他们的像素信息作为训练,验证和测试集,
,但这显然是非常非常大,最终导致计算机释放或耗尽磁盘空间。
当计算机死机时,正在生成的pkl文件为28GB。
我不确定这是不是应该这么大。
我做错了什么吗?或者有没有更有效的方法?
from PIL import Image
import pickle
import os
indir1 = 'Positive'
indir2 = 'Negative'
trainimage = []
trainpixels = []
trainlabels = []
validimage = []
validpixels = []
validlabels = []
testimage = []
testpixels = []
testlabels = []
i=0
for (root, dirs, filenames) in os.walk(indir1):
print 'hello'
for f in filenames:
try:
im = Image.open(os.path.join(root,f))
if i<40000:
trainpixels.append(im.tostring())
trainlabels.append(0)
elif i<45000:
validpixels.append(im.tostring())
validlabels.append(0)
else:
testpixels.append(im.tostring())
testlabels.append(0)
print str(i)+'t'+str(f)
i+=1
except IOError:
continue
i=0
for (root, dirs, filenames) in os.walk(indir2):
print 'hello'
for f in filenames:
try:
im = Image.open(os.path.join(root,f))
if i<40000:
trainpixels.append(im.tostring())
trainlabels.append(1)
elif i<45000:
validpixels.append(im.tostring())
validlabels.append(1)
else:
testpixels.append(im.tostring())
testlabels.append(1)
print str(i)+'t'+str(f)
i+=1
except IOError:
continue
trainimage.append(trainpixels)
trainimage.append(trainlabels)
validimage.append(validpixels)
validimage.append(validlabels)
testimage.append(testpixels)
testimage.append(testlabels)
output=open('data.pkl','wb')
pickle.dump(trainimage,output)
pickle.dump(validimage,output)
pickle.dump(testimage,output)
pickle文件格式不是特别有效,特别是对于图像而言。即使像素以每像素1字节的形式存储,也会有
50000报;240报;180 =;2160000000
so 2gb。您的像素无疑占用了更多的空间,我不确定PIL tostring()
方法在图像上实际做了什么。结果文件可能有几十gb,这是完全合理的。
您可能需要考虑使用pickle以外的存储方法。例如,简单地将文件以其本机映像格式存储在磁盘上,并pickle文件名列表有什么问题呢?
我同意您可能不应该将大量的pickle图像存储到磁盘上…除非您绝对需要(无论出于何种原因)。你可能应该买一个真正大的磁盘,有一些真正好的内存,和大量的处理能力。
无论如何,如果你把你的图像数据传输到numpy。数组,使用scipy.ndimage.imread
,然后您可以使用numpy内部格式加上压缩将图像存储到磁盘。
有像klepto
这样的包可以让你很容易做到这一点。
>>> from klepto.archives import dir_archive
>>> from scipy import ndimage
>>> demo = dir_archive('demo', {}, serialized=True, compression=9, cached=False)
>>> demo['image1'] = ndimage.imread('image1')
>>> demo['image2'] = ndimage.imread('image2')
现在您有一个字典接口来numpy内部表示压缩的pickle图像文件,在名为demo
的目录中每个文件有一个图像(也许您需要添加fast=True
标志,我不记得了)。所有的字典方法几乎都是可用的,因此您可以根据分析需要访问图像,然后使用del demo['image1']
或类似的方法丢弃pickle图像。
您还可以使用klepto
轻松地提供自定义编码,这样您就有了相当加密的数据存储。您甚至可以选择不加密/pickle数据,而只对磁盘上的文件有一个字典接口——这通常本身就很方便。
如果您不关闭缓存,您可能会达到计算机内存或磁盘大小的限制,除非您注意转储和加载映像到磁盘的顺序。在上面的示例中,我关闭了对内存的缓存,因此它直接写入磁盘。还有其他选项,例如使用内存映射模式和写入HDF文件。对于要在一台机器上处理的大型数组数据,我通常使用上面的方案,并且可能会选择MySQL归档后端来处理由多台机器并行访问的更小的数据。
在此获取klepto
: https://github.com/uqfoundation