开发者

Efficiently re-shaping a numpy ndarray from 2-D to 3-D based on elements from 2-D

开发者 https://www.devze.com 2023-03-15 02:16 出处:网络
I\'m working with DICOM files that contain image data.I am using pydicom to read the metadata from the .DCM file.Now, the pixel data that is extracted from the .DCM file is returned as a 2 dimensional

I'm working with DICOM files that contain image data. I am using pydicom to read the metadata from the .DCM file. Now, the pixel data that is extracted from the .DCM file is returned as a 2 dimensional numpy ndarray.

The particular DICOM files I am working with save a single intensity value per pixel. After I perform some manipulation on them I end up with a single floating point value (between 0.0 and 1.0) per pixel in a 2 dimensional 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.7448开发者_如何学Go0969, 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],

]

I would like to transform this into a 3-D ndarray with numpy by replacing each element with a sequence of elements [R, G, B] where R=G=B=intensity value.

The ndarray.put() function flattens out the matrix which rules out that method.

I also tried:

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] ]

but get a

ValueError: setting an array element with a sequence.   

Suggestions? I'm trying to keep data manipulation as light as possible because some of these images are huge, so I want to avoid a hack/manually copying all the data to a separate variable.

Thanks in advance for any help.


So what you want, of course, is an array of shape m x n x r, where r is the tuple size.

One way to do this, which seems to me the most straightforward, is to: (i) explicitly create a 3D grid array, identical to your original 2D arrayexcept for addition of the last dimension, r, which has been added, and then; (ii) map your rgb tuples onto this Grid.

>>> # 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]])

Now create the Grid array:

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

Think of G as an m x n rectangular grid--same as D--but with each of the 20 cells storing not an integer (like D) but an rgb tuple, so:

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

To grok this construction, you can see the rgb tuple w/in the Grid, G, by looking at three consecutive slices of 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)

Now to actually get the result you want, we just need to (i) create a grid, G, a 3D NumPy array, whose first two dimensions are taken from the array stored in your .DCM file, and whose third dimension is three, from the length of an rgb tuple; then (ii) map the rgb tuples onto that grid, 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)
0

精彩评论

暂无评论...
验证码 换一张
取 消