3

我正在 Kaggle 上进行 CIFAR 挑战。

他们提供了一个 .7z 文件,其中包含 50k 张图片作为训练。我花了 1 个小时解压缩它,然后又花了 40 分钟来读取所有文件并将其放入内存中。

尝试不创建 50k 文件,因为这是瓶颈,我已经安装了 pylzma 和其他库,但它们都会告诉我文件无效。

来自 bash 的 7z,可以正确读取文件,并列出文件。所以我使用Popenbash 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 ,它会为我转换它。

4

3 回答 3

9

虽然 skimage.io.imread 的文档说第一个参数是文件名的字符串,但我发现它也接受类似文件的对象(skimage 版本为 0.10.0)。

因此,您可以像这样将图像数据读入内存:

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],
        ...,
于 2014-09-05T09:14:11.980 回答
2

第一个参数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()处理 URL 时会自行执行此操作。

  • 使用命名管道。打开管道进行读取imread(),然后将数据写入管道。您可能需要线程或多处理来执行此操作。
于 2014-08-30T13:51:33.393 回答
1

浏览 skimage 代码,我发现他们可以与另一个图像库 PIL 集成。该库具有直接从打开的文件指针获取图像信息的功能。

在我的例子中,文件指针是一个 StringIO,所以它可以读取数据并识别它是关于什么的。

mhawke,谢谢你的帮助。在我看来,您的解决方案也可以,但我不想处理图像数据本身。

我已将代码放在 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
于 2014-08-31T09:36:41.813 回答