我正在对Kaggle进行CIFAR挑战。
他们提供了一个包含5万张图片的.7z文件作为火车。我花了1个小时解压缩它,然后又花了40分钟读取所有文件并将其存放在内存中。
尝试不创建50k文件,因为这是其中的瓶颈,我已经安装了pylzma和其他库,但是所有这些文件都告诉我该文件无效。
来自bash的7z,可以正确读取文件,并列出文件。所以我使用Popen
解压缩所有文件并使用bash 7z程序将其放入内存中的字符串
import subprocess
p = subprocess.Popen(["7z", "e", "-so", "awa.7z"], stdout=subprocess.PIPE).communicate()[0]
我设法通过查看每个文件的大小来获取每个文件,然后从字符串中获取相应的字节
f1 = p[0][0:2105]
我现在想要的是欺骗Python认为F1文件指针,这样我就可以调用skimage.io.imread并将它转换为适当的结构。或者也许只是将内存值传递给skimage,它会为我转换它。
答案 0 :(得分:5)
虽然skimage.io.imread的doc说第一个参数是filename的字符串,但我发现它也接受类似文件的对象(版本为0.10.0的skimage)。
因此您可以将图像数据读入内存,如下所示:
from StringIO import StringIO
with open(filename) as f:
img_data = f.read()
decoded_img_data = skimage.io.imread(StringIO(img_data))
print decoded_img_data
>> OUTPUT:
array([[[235, 230, 234],
[233, 228, 232],
[231, 226, 230],
...,
答案 1 :(得分:1)
skimage.io.imread()
的第一个参数是要从中读取的图像文件的名称,因此您将无法使用字符串中保存的图像数据来欺骗它。选项(为方便起见):
直接使用imread
包 - 请参阅imread.imread_from_blob()
。这会返回numpy.ndarray
(与skimage.io.imread
相同)。您需要知道图像文件类型(jpg,png,gif等),因为它必须作为第二个参数传递:
from imread import imread_from_blob
img_data = imread_from_blob(f1, 'jpg')
>>> img_data
array([[[ 23, 123, 149],
[ 22, 120, 147],
[ 22, 118, 143],
...,
etc.
将数据写入临时文件,然后使用imread()
打开该临时文件。 imread()
在处理网址时会自行执行此操作。
imread()
打开管道进行读取,然后将数据写入管道。您可能需要线程或多处理才能执行此操作。答案 2 :(得分:1)
浏览skimage代码,我发现他们可以与另一个图像库PIL集成。该库具有直接从打开的文件指针获取图像信息的功能。
就我而言,文件指针是一个StringIO,因此它可以读取数据并识别它的内容。
mwwke,谢谢你的帮助。在我看来,您的解决方案也可以正常工作,但我不想处理图像数据本身。我把代码放在github中(它只是一个骨架,但正在工作),如果有人感兴趣的话,这里是花哨的页面 http://adrianow.github.io/7z_on_array/
解决方案的一小部分:
import numpy as np
from PIL import Image
from StringIO import StringIO
# begin and end of each file
low = 0
up = 0
images = [0] *len(p_f_list)
# get each file from the byte file
for i, f in enumerate(p_f_list):
up += int(f[0])
# get bytes from the array
raw_img = p_f_data.data[low:up]
low = up
# Convert rawImage to Mat
pil_image = Image.open(StringIO(raw_img))
np_image = np.array(pil_image)
images[i] = np_image