2

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

]

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.

Suever
  • 64,497
  • 14
  • 82
  • 101
Luke Mueller
  • 263
  • 2
  • 8

1 Answers1

2

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)
doug
  • 69,080
  • 24
  • 165
  • 199
  • This method worked well and I successfully got what I wanted. However, all R G and B values will be the same in this particular instance so I just set G[:,:,0] = 2-D Array G[:,:,1] = 2-D Array G[:,:,2] = 2-D Array and I get the results I wanted. P.S. the np.zeroes function was very useful I don't know how I missed that in the docs – Luke Mueller Jun 27 '11 at 15:45