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, и он преобразует их для меня.
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(). Это возвращает anumpy.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