Эффективное изменение формы numpy ndarray из 2-D в 3-D на основе элементов из 2-D

Я работаю с файлами DICOM, которые содержат данные изображений. Я использую pydicom для чтения метаданных из файла .DCM. Теперь данные пикселей, извлеченные из файла .DCM, возвращаются в виде двумерного массива numpy ndarray.
Конкретные файлы DICOM, с которыми я работаю, сохраняют одно значение интенсивности на пиксель. После некоторых манипуляций с ними я получаю одно значение с плавающей запятой (от 0,0 до 1,0) на пиксель в двумерном массиве ndarray:

[

[ 0.98788927, 0.98788927 0.98788927, ..., 0.88062284 0.89532872 0.87629758],
[ 0.98788927, 0.98788927, 0.98788927, ..., 0.8884083, 0.89446367, 0.87889273],
[ 0.98788927, 0.98788927, 0.98788927, ..., 0.89100346, 0.89532872, 0.87629758],
,...,
[ 0.97491349, 0.97491349, 0.97491349, ..., 0.74480969, 0.72318339, 0.73269896],
[ 0.97491349, 0.97491349, 0.97491349, ..., 0.74913495, 0.74480969, 0.74740484],
[ 0.97491349, 0.97491349, 0.97491349, ..., 0.74913495 0.75865052, 0.75086505],

]

Я хотел бы преобразовать это в трехмерный ndarray с numpy, заменив каждый элемент последовательностью элементов [R, G, B], где R = G = B = значение интенсивности.

Функция ndarray.put () выравнивает матрицу, исключающую этот метод.

Я также пробовал:

for x in range( len(a[0]) ):
  for y in range( len(a) ):
    a[x][y] = [ a[x][y], a[x][y], a[x][y] ]

но получить

ValueError: setting an array element with a sequence.   

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

Заранее благодарю за любую помощь.


person Luke Mueller    schedule 24.06.2011    source источник
comment
Думаю, что-то упускаю. Почему numpy.array([a,a,a]) не работает?   -  person Stephen Terry    schedule 25.06.2011
comment
numpy.array ([a, a, a]) должен быть намного быстрее, поскольку вы явно не выполняете итерацию по вашему массиву.   -  person matt    schedule 25.06.2011


Ответы (1)


Итак, вам, конечно же, нужен массив формы m x n x r, где r - размер кортежа.

Один из способов сделать это, который мне кажется наиболее простым, состоит в следующем: (i) явно создать массив трехмерной сетки, идентичный исходному двумерному массиву, за исключением добавления последнего измерения, r, которое был добавлен, а затем; (ii) сопоставьте свои rgb-кортежи с этой сеткой.

>>> # first, generate some fake data:
>>> m, n = 5, 4            # rows & cols, represents dimensions of original image
>>> D = NP.random.randint(0, 10, m*n).reshape(m, n)
>>> D
    array([[8, 2, 2, 1],
           [7, 5, 0, 9],
           [2, 2, 9, 3],
           [5, 7, 3, 0],
           [5, 8, 1, 7]])

Теперь создайте массив Grid:

>>> G = NP.zeros((m, n, r), dtype='uint')

Думайте о G как о прямоугольной сетке m x n - такой же, как D - но с каждой из 20 ячеек, хранящих не целое число (например, D), а кортеж rgb, поэтому:

>>> # placing the color pixel (209, 127, 87) at location 3,2:
>>> G[3,2] = (209, 124, 87)

Чтобы понять эту конструкцию, вы можете увидеть кортеж rgb w / в сетке, G, посмотрев на три последовательных фрагмента G:

>>> G[:,:,0]      # red
>>> array([[  0,   0,   0,   0,   0],
           [  0,   0,   0,   0,   0],
           [  0,   0,   0,   0,   0],
           [  0,   0, 209,   0,   0],
           [  0,   0,   0,   0,   0]], dtype=uint8)

>>> G[:,:,1]    # green
>>> array([[  0,   0,   0,   0,   0],
           [  0,   0,   0,   0,   0],
           [  0,   0,   0,   0,   0],
           [  0,   0, 124,   0,   0],
           [  0,   0,   0,   0,   0]], dtype=uint8)

>>> G[:,:,2]   # blue
>>> array([[ 0,  0,  0,  0,  0],
           [ 0,  0,  0,  0,  0],
           [ 0,  0,  0,  0,  0],
           [ 0,  0, 87,  0,  0],
           [ 0,  0,  0,  0,  0]], dtype=uint8)

Теперь, чтобы получить желаемый результат, нам просто нужно (i) создать сетку G, трехмерный массив NumPy, первые два измерения которого взяты из массива, хранящегося в вашем файле .DCM, а третье измерение - три от длины кортежа rgb; затем (ii) отобразить наборы rgb на эту сетку G.

>>> # create the Grid
>>> G = NP.zeros((m, n, r), dtype='uint')
>>> # now from the container that holds your rgb tuples, create *three* m x n arrays, 
>>> # one for each item in your rgb tuples

>>> # now just map the r values (1st itm in each rgb tuple) to the 3D grid
>>> G[:,:,0] = r_vals
>>> G[:,:,1] = g_vals
>>> G[:,:,2] = b_vals

>>> G.shape
    (5, 4, 3)
person doug    schedule 25.06.2011
comment
Этот метод сработал, и я успешно получил то, что хотел. Однако все значения RG и B в этом конкретном случае будут одинаковыми, поэтому я просто установил G [:,:, 0] = 2-D Array G [:,:, 1] = 2-D Array G [:,: , 2] = 2-мерный массив, и я получаю желаемые результаты. P.S. функция np.zeroes была очень полезной, я не знаю, как я пропустил это в документации - person Luke Mueller; 27.06.2011