@Re7r0

Как в numpy максимально быстро изменить структуру данных в массиве?

Есть трехмерный массив изображения, полученный в результате: image = cv2.imread("image.png").
Нужно преобразовать из RGB в decimal все элементы массива, то есть например: из RGB(255, 0, 255) в "16711935".
Максимально примитивный и неэффективный код для лучшего понимания:
image = cv2.imread("image.png")
image_clon = numpy.zeros((image.shape[0], image.shape[1]))

for y in range(image.shape[0], 1):

    for x in range(image.shape[1], 1):
        image_clon[y][x] = (image[y][x][0] * 256 * 256) + (image[y][x][1] * 256) + image[y][x][2]


UPD: благодарю mayton2019 за активность, все решил с помощью PYCUDA
  • Вопрос задан
  • 108 просмотров
Пригласить эксперта
Ответы на вопрос 3
mayton2019
@mayton2019
Bigdata Engineer
CUDA это хорошо. Вот еще Питончик. Прошу прощения за scala-style. Рука машинально typetags пишет...
from PIL import Image
import numpy as np

img : PIL.PngImagePlugin.PngImageFile = Image.open("pic-001.png")

if img.mode != 'RGB':
  img = img.convert('RGB')

img_data : np.ndarray = np.array(img)

width : int  = img_data.shape[0]
height : int = img_data.shape[1]

dest_data : np.ndarray = np.zeros((width, height), dtype=np.uint32)

for y in range(0, height):
  for x in range(0, width):
    pixel : np.ndarray = img_data[x,y]
    color : int = pixel[0] << 16 + pixel[1] << 8 + pixel[2]
    dest_data[x,y] = color
Ответ написан
Комментировать
@U235U235
Еще вариант без for:

b=np.array([256*256,256,1], dtype=np.uint32) # or [1, 256, 256*256] BGR<->RGB
result=image@b
Ответ написан
Vindicar
@Vindicar
RTFM!
CUDA тут не нужна, просто не следует перебирать массив numpy питоновскими циклами.
Если есть возможность - выражай желаемое через операции над массивом в целом. Тогда цикл организует numpy, и он это делает через нативный код, ЕМНИП - работает в разы быстрее.
Подход ниже сожрёт больше памяти, но зато короткий, выразительный и использует только средства numpy.
image = cv2.imread("image.png")
image = image.astype(numpy.uint32)  # смена типа нужна, иначе при сдвиге потеряются разряды
image_clone = (image[..., 0] << 16) | (image[..., 1] << 8) | image[..., 2]

Если хочется заморочиться по памяти:
image = cv2.imread("image.png")
image_clone = numpy.zeros(image.shape[:2], numpy.uint32)
# краткие формы операций не создают новый массив, а изменяют существующий по месту
image_clone |= image[..., 0]
image_clone <<= 8
image_clone |= image[..., 1]
image_clone <<= 8
image_clone |= image[..., 2]


P.S.: как там, у imread() починили уже неумение работать с юникодными путями?
Ответ написан
Комментировать
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы