Python string as file в Skimage imread



Я делаю вызов CIFAR на Kaggle.



Они дали А.7z файл, содержащий 50k картинок в виде поезда. Мне потребовался 1 час, чтобы распаковать его, а затем еще 40 минут, чтобы прочитать весь файл и поместить его в память.



Пытаясь не создавать файлы 50k, так как это узкое место этого, я установил pylzma и другие библиотеки, но все они скажут мне, что файл не является допустимым.



7z от bash, может правильно прочитать файл и перечислить файлы. Поэтому я воспользовался 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, и он преобразует их для меня.

641   3  

3 ответов:

Хотя doc из 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],
        ...,

Первый параметр для skimage.io.imread() - это имя файла изображения, из которого нужно читать, поэтому вы не сможете обмануть его, используя данные изображения, хранящиеся в строке. Варианты (в порядке удобства):

  • Используйте imread пакет непосредственно-см. imread.imread_from_blob(). Это возвращает a 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(), затем запишите данные в канал. Для этого могут потребоваться потоки или многопроцессорная обработка.

Просматривая код 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

Comments

    Ничего не найдено.