превышен максимально допустимый размер - PullRequest
0 голосов
/ 13 января 2019

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

Вот код:

import matplotlib.pyplot as plt
import matplotlib.cm as cm
import numpy as np

boshi = 123456789098765432135790864234579086542098765432135321 # universal mass

genesis = boshi ** 31467 # padding

artifice = np.binary_repr(genesis) # formatting

A = int(artifice) 

D = np.array(A).reshape(A, (1348, 4117))

plt.imsave('hello_world.png', D, cmap=cm.gray) # save image

Я продолжаю сталкиваться с ошибкой на D = np.array..., и, возможно, мое изменение формы слишком велико, но только немного больше, чем 4k. Похоже, что это не должно быть проблемой для GPU улучшенного Colab. Не запускается и на моей домашней машине с той же ошибкой. Это будет исправлено с большим количеством оперативной памяти?

Ответы [ 2 ]

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

Как это работает

Проблема в том, что artifice = np.binary_repr(genesis) создает строку. Строка состоит из 1348 * 4117 = 5549716 цифр, все они из нулей и единиц. Если вы преобразуете строку в целое число Python, A = int(artifice), вы будете (A) ждать очень долго и (B) получать не повторяемый объект. Массив, который вы создаете с помощью np.array(A), будет содержать один элемент.

Хорошей новостью является то, что вы можете полностью обойти трудоемкий шаг, используя тот факт, что строка artifice уже итеративна:

D = np.array(list(artifice), dtype=np.uint8).reshape(1348, 4117)

Шаг list(artifice) займет пару секунд, так как должен разделить строку, но все остальное должно быть довольно быстрым.

Оттуда легко составить график plt.imsave('hello_world.png', D, cmap=cm.gray):

enter image description here

* 1027 цветовые карты *

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

plt.imsave('hello_world2.png', D, cmap=cm.coolwarm)

enter image description here

Exploration

У вас есть возможность добавить множество цветов к вашему изображению. Обычно PNG является 8-битным. Например, вместо преобразования genesis в биты, вы можете взять из него байты для построения изображения. Вы также можете взять полубайты, чтобы создать индексированное изображение с 16 цветами. С небольшими отступами вы даже можете убедиться, что у вас есть кратные три точки данных, и создать полноцветное изображение RGB любым количеством способов. Я не буду вдаваться в более сложные варианты, но я хотел бы изучить возможность создания простого изображения из байтов.

5549716 бит - это 693715 = 5 * 11 * 12613 байт (с четырьмя ведущими нулевыми битами). Это очень неприятная факторизация, приводящая к размеру изображения 55x12613, поэтому давайте уберем этот верхний клев: в то время как факторизация 693716 столь же плоха, как 693715, 693714 очень хорошо вписывается в 597 * 1162.

Вы можете преобразовать целое число в массив байтов, используя собственный метод to_bytes:

from math import ceil

byte_genesis = genesis.to_bytes(ceil(genesis.bit_length() / 8), 'big')

Причина, по которой я использую встроенный ceil вместо np.ceil, заключается в том, что он возвращает целое число, а не число с плавающей точкой.

Преобразование огромного целого числа происходит очень быстро, поскольку объект bytes имеет прямой доступ к данным целого числа: даже если он создает копию, он практически не обрабатывается. Он может даже совместно использовать буфер, так как bytes и int являются номинально неизменяемыми. Точно так же вы можете создать простой массив из bytes как просто представление той же области памяти, используя np.frombuffer:

img = np.frombuffer(byte_genesis, dtype=np.uint8)[1:].reshape(597, 1162)

* * * * * * * * * * * * * * * * * * * * * * * *). [1:] необходим, чтобы отрубить ведущий кусок, так как bytes_genesis должен быть достаточно большим, чтобы вместить всего genesis. Вы также можете отрубить на стороне bytes:

img = np.frombuffer(byte_genesis[1:], dtype=np.uint8).reshape(597, 1162)

Результаты идентичны. Вот как выглядит картинка:

plt.imsave('hello_world3.png', img, cmap=cm.viridis)

Результат слишком велик для загрузки (потому что это не двоичное изображение), но вот случайно выбранный образец:

enter image description here

Я не уверен, что это эстетически то, что вы ищете, но, надеюсь, это даст вам возможность начать искать способы преобразования очень больших чисел в буферы данных.

Дополнительные параметры, потому что это интересно

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

temp = np.frombuffer(byte_genesis, dtype=np.uint8)[1:]

Вот один из способов распаковать клев:

img = np.empty((1162, 1194), dtype=np.uint8)
img.ravel()[::2] = np.bitwise_and(temp >> 4, 0x0F)
img.ravel()[1::2] = np.bitwise_and(temp, 0x0F)

С такой картой цветов, как jet, вы получите:

plt.imsave('hello_world4.png', img, cmap=cm.jet)

enter image description here

Другой вариант, если говорить в противоположном направлении), вообще не использовать цветовые карты. Вместо этого вы можете разделить свое пространство в три раза и генерировать свои собственные цвета в пространстве RGB. К счастью, одним из главных факторов 693714 является 3. Таким образом, вы можете получить изображение размером 398x581 (693714 == 3 * 398 * 581). То, как вы интерпретируете данные, остается за вами.

Примечание, прежде чем я продолжу

С помощью черно-белого двоичного изображения вы можете контролировать цвет, размер и ориентацию изображения. С 8-битными данными вы можете управлять тем, как отбираются биты (8 или меньше, как в 4-битном примере), порядком байтов вашей интерпретации, цветовой картой и размером изображения. С полноцветным цветом вы можете рассматривать каждую тройку как отдельный цвет, обрабатывать весь набор данных как три последовательные цветовые плоскости или даже делать что-то вроде применения фильтра Байера к массиву. Все в дополнение к другим параметрам, таким как размер, порядок, количество бит на выборку и т. Д.

Далее будут показаны варианты цветовых троек и трех цветовых плоскостей.

Полноцветные изображения

Чтобы рассматривать каждый набор из 3 последовательных байтов как тройку RGB, вы можете сделать что-то вроде этого:

img = temp.reshape(398, 581, 3)
plt.imsave('hello_world5.png', img)

Обратите внимание, что в этом случае нет цветовой карты.

enter image description here

Интерпретация данных в виде трех цветовых плоскостей требует дополнительного шага, поскольку plt.imsave ожидает, что последнее измерение будет иметь размер 3. np.rollaxis - хороший инструмент для этого:

img = np.rollaxis(temp.reshape(3, 398, 581), 0, 3)
plt.imsave('hello_world6.png', img)

enter image description here

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

Я не смог воспроизвести вашу проблему, потому что строка A = int(artifice) проходила как всегда. Я заменил его на цикл for, чтобы привести каждую цифру к себе. Код работал тогда и генерировал желаемое изображение.

import matplotlib.pyplot as plt
import matplotlib.cm as cm
import numpy as np

boshi = 123456789098765432135790864234579086542098765432135321
genesis = boshi ** 31467
artifice = np.binary_repr(genesis)

D = np.zeros((1348, 4117), dtype=int)
for i, val in enumerate(D):
    D[i] = int(artifice[i])

plt.imsave('hello_world.png', D, cmap=cm.gray)
...