Чтение массивов попиксельно, получение UnpicklingError - PullRequest
0 голосов
/ 29 августа 2018

Я ранее сохранил тысячи двумерных массивов (600x600) в двоичный файл с pickle. Я сохранил их один за другим из-за ограничений памяти, и теперь я хотел бы прочитать их один за другим, выполнить некоторые операции и сохранить новые массивы (также по одному) в новый файл. Затем моя последняя цель - прочитать эти новые массивы один за другим и добавить значение пикселя в новый список, соответствующий данной позиции. Но по какой-то причине я получаю UnpickingError, и я не знаю почему.

import numpy as np
import pickle

def normalize(data_set):
    data_set *= 1/data_set.max()
    with open('final_images.data', 'a+b') as f:
        pickle.dump(data_set, f)
    return data_set

with open('initial_data.data', 'rb') as f:
    while True:
        try:
            data_set = pickle.load(f)
            # other operations
            final_img = normalize(data_set)
        except EOFError:
            break

filename = 'final_images.data'
def sort_by_pixel(i, j):
    pixels_at_position = []
    with open(filename, 'rb') as f:
        while True:
            try:
                array = pickle.load(f) #GET ERROR HERE
                fp = np.memmap(filename, dtype='float32', mode='w+', shape=(600,600))
                fp[:] = array[:]
                pixels_at_position.append(fp[i][j])
            except EOFError:
                break
    return pixels_at_position

stacked = []
for i in range(600):
    for j in range(600):
        stacked.append(np.median(sort_by_pixel(i, j)))

Ошибка, которую я получаю в указанной строке:

pickle.UnpicklingError: invalid load key, '\x00'.

Что я делаю не так?

1 Ответ

0 голосов
/ 29 августа 2018

У вас есть совершенно правильный файл рассола, final_images.data, к которому вы добавили дампы рассола. Итак, в первый раз через цикл, array = pickle.load(f) будет работать.

Но тогда вы отображаете тот же файл:

fp = np.memmap(filename, dtype='float32', mode='w+', shape=(600,600))

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

Но затем вы перезаписываете весь файл необработанными данными массива последнего загруженного вами пакета:

fp[:] = array[:]

И теперь файл больше не является допустимым файлом рассола, это необработанные данные.

Итак, в следующий раз через цикл, когда вы pickle.load выйдете из него, произойдет сбой, который даст вам именно ту ошибку, которую вы видите. 1 .


Если вам действительно нужен mmap, вы хотите сохранить его в другом файле, а не перезаписывать файл pickle, который вы читаете:

fp = np.memmap(filename + '.raw', dtype='float32', mode='w+', shape=(600,600))

Но на самом деле, я не вижу, что хорошего делает mmap в первую очередь. У вас уже есть тот же массив в памяти, что и array. Создание memmap и последующее копирование данных в него - просто бесполезная трата ресурсов, которые я не вижу. Если вы просто удалите эту строку и выполните pixels_at_position.append(array[i][j]), она должна иметь тот же эффект, что и после. 2

На самом деле я не уверен, это то, что вам нужно, потому что ваш код, похоже, пытается сделать это создать список (i, j) -ых значений каждого массива в рассоле, но название функции, sort_by_pixel, звучит так, как будто вы действительно хотите что-то совершенно отличное от этого (что-то отсортированное, с одной стороны).


1. На самом деле, это потерпит неудачу, только если вам повезет. Если исходные данные достаточно малы. указатель файла f может быть за концом, и вы просто получите EOF. И если вам действительно не повезло, необработанные данные могут оказаться интерпретируемыми как маринада для кортежа объектов даты-времени или чего-то сумасшедшего, и вы просто тихо произведете тонну мусора.

2. За исключением того, что вы действительно должны использовать [i, j], а не [i][j]. Последний должен создать объект строки только для того, чтобы он мог его проиндексировать. Это не слишком дорого, поскольку строка представляет собой просто фрагмент в той же памяти, что и исходный массив, но все еще не свободна. И это также менее идиоматично и, следовательно, менее понятно - кто-то, читающий [i, j], знает, что вы индексируете двумерный массив; кто-то читает [i][j] будет ожидать, что вы индексируете (возможно, зубчатую) последовательность последовательностей, и должен выяснить, что это на самом деле двумерный массив.

...