Есть ли более быстрый способ сохранить 2d NumPy массивов в PNG - PullRequest
2 голосов
/ 04 июля 2019

Привет, я новичок в python и пытаюсь сохранить двумерный массив с numpy в файл png.

Каждый элемент моего двумерного массива является целым числом от 0 до 100, и у меня естьgetColor() функция для отображения в значения RGB.То, что я сейчас делаю, - это создание 3-канального массива NUMPY такой же формы, как у моего 2D NUMPY массива, и сопоставление каждого значения с соответствующими значениями RGB.Однако, это занимает много времени, и я чувствую, что должен быть намного более эффективный способ сделать это.Мой код в настоящее время занимает около 5 секунд для обработки одного изображения.

import numpy as np
import imageio

flt_m = get2dArray() # returns a (880*880) numpy array

def getColor(value):
    if(value < 0):
        return (0,0,0)
    elif(value < 50):
        return (100,150,200)
    else:
        return (255,255,255)

canvas = np.zeros((flt_m.shape[0], flt_m.shape[1], 3)).astype(np.uint8)
for row in range(flt_m.shape[0]):
    for col in range(flt_m.shape[1]):
        rgb = getColor(flt_m[row, col])
        for i in range(3):
            canvas[row, col, i] = rgb[i]

imageio.imwrite('test.png', canvas) # saves file to png

Ответы [ 2 ]

4 голосов
/ 04 июля 2019

Вы можете использовать логическое индексирование для числовых массивов для установки различных подмножеств массива.

Так что, возможно, вы используете:

canvas = np.ones([880, 880, 3], dtype=np.uint8) * 255   # initialize the whole RGB-Array with (255, 255, 255)

canvas[flt_m<50] = (100, 150, 200)      # set all values where flt_m is <50 to (100, 150, 200)

Однако, если у вас есть отрицательные значения в flt_m, вы все равно можете добавить

canvas[flt_m<0] = (0, 0, 0)
3 голосов
/ 04 июля 2019

У вас уже есть хорошее решение с ответом @SpghttCd, но ваше время записи кажется очень медленным, поэтому я подумал об альтернативном решении ...

Поскольку в вашем изображении только 2-3 цвета, вы можете написать изображение с палитрой (которое будет поддерживать до 256 цветов), что потребует меньше памяти, меньше обработки и меньше места на диске. Вместо того чтобы хранить 3 байта (1 для красного, 1 для зеленого и 1 для синего) для каждого пикселя, он сохраняет один байт на каждый пиксель, и этот байт является индексом для таблицы или палитры поиска RGB 256 цветов.

import numpy as np
from PIL import Image

# Generate synthetic image of same size with random numbers under 256
flt_im = np.random.randint(0,256,(880,880), dtype=np.uint8)

# Make numpy array into image without allocating any more memory
p = Image.fromarray(flt_im, mode='L')

# Create a palette with 256 colours - first 50 are your blueish colour, rest are white
palette = 50*[100,150,200] +  206*[255,255,255]

# Put palette into image and save
p.putpalette(palette)
p.save('result.png')

Очевидно, что я не могу проверить производительность на вашем компьютере, но если я сравню свою версию с палитрой и версию SpghttCd, я получу значительную разницу в скорости в 50 раз:

def SpghttCd(flt_im):
    canvas = np.ones([880, 880, 3], dtype=np.uint8) * 255

    canvas[flt_im<50] = (100, 150, 200)
    imageio.imwrite('SpghttCd.png', canvas)


def me(flt_im):
    # Make numpy array into image without allocating any more memory
    p = Image.fromarray(flt_im, mode='L')

    # Create a palette with 256 colours - first 50 are your blueish colour, rest are white
    palette = 50*[100,150,200] +  206*[255,255,255]

    # Put palette into image and save
    p.putpalette(palette)
    p.save('result.png')

# Generate random data to test with - same for both
flt_im = np.random.randint(0,256,(880,880), dtype=np.uint8)

%timeit me(flt_im)
In [34]: %timeit me(flt_im)                                                                         
34.1 ms ± 1.06 ms per loop (mean ± std. dev. of 7 runs, 10 loops each)

In [37]: %timeit SpghttCd(flt_im)                                                                   
1.68 s ± 7.17 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)

Я отмечаю, что переход от PNG к GIF (который столь же способен для этого типа вещей) приводит к дальнейшему увеличению скорости в 7 раз, то есть 5 мс вместо 34 мс.

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