Python字符串作为Skimage imread中的文件

时间:2014-08-30 12:09:05

标签: python file decode scikit-image

我正在对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,它会为我转换它。

3 个答案:

答案 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