Параметр размера для gzip.open (). Read () - PullRequest
0 голосов
/ 03 января 2019

При работе с библиотекой gzip в Python очень часто я сталкивался с кодом, который использует функцию .read() в шаблоне, который выглядит следующим образом:

with gzip.open(filename) as bytestream:
    bytestream.read(16) 
    buf = bytestream.read(
        IMAGE_SIZE * IMAGE_SIZE * num_images * NUM_CHANNELS
    )
    data = np.frombuffer(buf, dtype=np.uint8).astype(np.float32)

Пока язнакомый с шаблоном диспетчера контекста, я изо всех сил пытаюсь понять, что вообще делает первая строка кода в диспетчере контекста with.

Это документация для функции read():

Чтение не более n символов из потока.

Чтение из нижележащего буфера, пока у нас не будет n символов или мы не нажмем EOF.Если n отрицательно или опущено, читайте до EOF.

Если это так, функциональная роль первой строки bytestream.read(16) должна заключаться в чтении и, таким образом, пропуске первых 16 символов, предположительнопотому что они действуют как метаданные или заголовок.Однако, когда у меня есть несколько изображений, как я узнаю, как использовать 16 в качестве аргумента для вызова read вместо, скажем, 32 или, 8 или 64?

Я вспомнил много раз, когда сталкивался с полностью идентичным кодом, описанным выше, за исключением того, что автор использовал bytestream.read(8) вместо bytestream.read(16) или, что вполне вероятно, любое другое значение.Копание в файл посимвольно не показывает видимого шаблона для определения длины символа заголовка.

Другими словами, как один определяет параметр, который будет использоваться при вызове функции read? или как узнать длину символов заголовка в сжатом gzip-файле?

Я предположил, что это как-то связано с байтами, но после поиска в документации и онлайн-ссылках я не могу это подтвердить.

Воспроизводимые детали

Моя гипотеза, после бесчисленных часов устранения неполадок, состоит в том, что первые 16 символов представляют собой своего рода заголовок или метаданные.Итак, первая строка в этом коде - пропустить 16 символов и сохранить оставшиеся в переменной с именем buf.Однако, копаясь в данных, я не нашел способа определить, почему или как было выбрано значение 16.Я прочитал байты символ за символом, а также попытался прочитать + и привести их к типу np.float, но нет никаких заметных шаблонов, которые предполагают, что метаданные заканчиваются 16-м символом, а фактические данные начинаются 17-го.

Следующий код читает данные с этого сайта и извлекает первые 30 символов.Обратите внимание, что неразличимо, где строка заголовка «заканчивается» (шестнадцатая, очевидно, после второго появления \ x1c`), и данные начинаются:

import gzip
import numpy as np

train_data_filename = 'data_input/train-images-idx3-ubyte.gz'
IMAGE_SIZE = 28
NUM_CHANNELS = 1

def extract_data(filename, num_images):
    with gzip.open(filename) as bytestream:
        first30 = bytestream.read(30)
        return first30

first30= extract_data(train_data_filename, 10)
print(first30)
# returns: b'\x00\x00\x08\x03\x00\x00\xea`\x00\x00\x00\x1c\x00\x00\x00\x1c\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'

Если мы изменим код, чтобы привести их к виду np.float32, так что все символы теперь были в числовом формате (с плавающей запятой), опять же не было очевидного шаблона, чтобы различать, где заканчиваются заголовок / метаданные и где начинаются данные.

Любая ссылка или совет будут очень благодарны!

Ответы [ 2 ]

0 голосов
/ 03 января 2019

С точки зрения gzip, все, что он вам возвращает, это данные. - это без метаданных или специфичного для gzip содержимого заголовка, добавленного к этому потоку данных, поэтому нет необходимости в каком-либо алгоритме, чтобы выяснить, сколько содержимого gzip предшествует этому потоку: количество байтов, к которым он добавляетсяноль.


Прокрутите вниз до нижней части страницы, на которую вы ссылаетесь;есть заголовок с именем ФОРМАТЫ ФАЙЛОВ ДЛЯ БАЗЫ ДАННЫХ MNIST .

Эта спецификация формата точно сообщает вам, что это за формат, и, следовательно, сколько байтов используется для каждого заголовка.В частности, первые четыре элемента в каждом файле описываются следующим образом:

0000     32 bit integer  0x00000803(2051) magic number 
0004     32 bit integer  60000            number of images 
0008     32 bit integer  28               number of rows 
0012     32 bit integer  28               number of columns 

Таким образом, если вы хотите пропустить все четыре из этих элементов, вы удалите 16 байтов с верха.

0 голосов
/ 03 января 2019

Из фрагмента кода bytestream.read(16) читает или пропускает первые 16 байтов потока байтов.Когда вы цитируете, что read () читает не более n символов из потока, это так, но также оказывается, что python хранит один символ в 1 байте, в результате чего 16 символов занимают 16 байтов.

Подробнее см. Насимволы и байты https://pymotw.com/3/gzip/#reading-compressed-data

Фрагмент кода в первую очередь интересует содержимое буфера, пропуская первые 16 байтов потока.Чтобы понять, как определить параметр, который входит в первый bytestream.read() AKA, определить, сколько байтов сжатого файла изображения пропустить, мы должны понять, что делает остальная часть кода.В частности, какой файл мы читаем и что мы пытаемся достичь с помощью библиотеки numpy (?) (Сохранение изображений rgb в массиве 1D numpy?).

Я определенно не специалист по обработке изображений, но этоКажется, что bytestream.read(16) является уникальным решением для уникальной проблемы обработки какого-либо уникального сжатого файла изображения.Таким образом, трудно сказать, как определить, сколько байтов пропустить, не видя больше кода и не понимая больше логики за фрагментом.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...