Измените размеры ndarray и умножьте содержимое

#python-3.x #numpy #python-imaging-library

#python-3.x #numpy #python-imaging-library

Вопрос:

У меня есть MxN ndarray, который содержит значения True и False внутри этих массивов, и я хочу нарисовать их в виде изображения. Цель состоит в том, чтобы преобразовать массив в изображение подушки с каждым истинным значением в качестве постоянного цвета. Я смог заставить его работать, прокручивая каждый пиксель и изменяя их по отдельности путем сравнения и рисования пикселя на пустом изображении, но этот метод слишком медленный.

 # img is a PIL image result
# image is the MxN ndarray

pix = img.load()
for x in range(image.shape[0]):
  for y in range(image.shape[1]):
     if image[x, y]:
       pix[y, x] = (255, 0, 0)
  

Есть ли способ изменить ndarray на MxNx3, заменив кортежи непосредственно на истинные значения?

Ответ №1:

Например, если у вас есть свой 2D-массив True / False и метка для цвета [255,255,255] , будет работать следующее:

 colored = np.expand_dims(bool_array_2d,axis=-1)*np.array([255,255,255])
  

Чтобы проиллюстрировать это на фиктивном примере: в следующем коде я создал случайную матрицу из 0 и 1, а затем превратил 1 в белый ([255,255,255]).

 import numpy as np
import matplotlib.pyplot as plt

array = np.random.randint(0,2, (100,100))
colors = np.array([255,255,255])
colored = np.expand_dims(array, axis=-1)*colors

plt.imshow(colored)
  

Надеюсь, это помогло

Комментарии:

1. Отличная работа! Возможно , вы захотите добавить .astype(np.uint8) в конец, иначе это может выглядеть как int64 и занимать в ОЗУ в 8 раз больше места, и PIL / Pillow не сможет сохранить его, например, в формате PNG. Хотя у вас уже есть мой голос 🙂

2. Большое вам спасибо. Да, я согласен с вами, в ситуации с интенсивными вычислениями или ограниченными возможностями приведение к uint_8 было бы абсолютно необходимо

3. Спасибо, это решение определенно то, к чему я стремился. Я нашел другое решение с преобразованием в изображение и обратным преобразованием, но это работает гораздо более универсально для массивов numpy.

Ответ №2:

Нашел другое решение, сначала преобразовал в изображение, затем преобразовал в RGB, затем преобразовал обратно в отдельный на 3 канала. Когда я пытался объединить несколько логических массивов вместе, этот способ был намного быстрее.

 img = Image.fromarray(image * 1, 'L').convert('RGB')
data = np.array(img)
red, green, blue = data.T
area = (red == 1)
data[...][area.T] = (255, 255, 255)
img = Image.fromarray(data)
  

Ответ №3:

Я думаю, вы можете сделать это довольно просто и быстро, вот так:

 # Make a 2 row by 3 column image of True/False values
im = np.random.choice((True,False),(2,3))                                                             
  

Мой выглядит так:

 array([[False, False,  True],
       [ True,  True,  True]])
  

Теперь добавьте новую ось, сделайте ее 3-канальной и умножьте значения истинности на ваш новый «цвет»:

 result = im[..., np.newaxis]*[255,255,255]                                                                     
  

что дает вам это:

 array([[[  0,   0,   0],
        [  0,   0,   0],
        [255, 255, 255]],

       [[255, 255, 255],
        [255, 255, 255],
        [255, 255, 255]]])