user1603454
user1603454

Reputation: 99

convert 4D .nii file to .png

I have a 4D .nii file like "filtered_func_data.nii" from: [https://nifti.nimh.nih.gov/nifti-1/data]

By loading the data and access the img field:

S = load_nii('filtered_func_data.nii')
S = 

       hdr: [1x1 struct]
  filetype: 2
fileprefix: 'filtered_func_data'
   machine: 'ieee-be'
       img: [4-D int16]
  original: [1x1 struct]

A = S.img

with size of:

size(A)

answer =

64    64    21   180

So the data consists of 64x64 images with a depth/number of slices of 21 and a number of frames of 180. Can someone please help me to convert this .nii data to 21*180= 3780 png images with the size of 64*64? Also, I want to remove the last 10 slices of each time course.

Upvotes: 2

Views: 1283

Answers (1)

gnovice
gnovice

Reputation: 125854

Firstly, you can remove the last 10 image volumes by indexing the array like so:

A = A(:, :, :, 1:170);

You'll also want to convert your data from 16-bit signed integers to 16-bit unsigned integers, since int16 isn't supported for PNG files (as the error message in your comment shows). My experience with medical images like this is that the vast majority of the image data lies in the positive range, with a few spurious negative pixel values, so you'd probably be fine just zeroing out the negative values and converting to an unsigned integer (you may want to look at a histogram of your pixel values to be sure):

A = uint16(A);  % Convert to unsigned, zeroing out negative values

Now, when you create all of your PNG images, you'll probably want to generate a file name that has the slice and time indices in it so you can identify and sort them easier. You can loop over every 64-by-64 image, generating a file name using sprintf and using imwrite to create the image like so:

[nRows, nCols, nSlices, nTimes] = size(A);
for iSlice = 1:nSlices
  for iTime = 1:nTimes
    fileName = sprintf('%s_%d_%d.png', S.fileprefix, iSlice, iTime);
    imwrite(A(:, :, iSlice, iTime), fileName);
  end
end

If you'd like to cut down on the number of files you generate, you could collect the 21 slices of each image volume into a 5-by-5 mosaic, giving you one larger image (320-by-320) per time point. You can do this as follows, using cell arrays, mat2cell and cell2mat:

[nRows, nCols, nSlices, nTimes] = size(A);
for iTime = 1:nTimes
  C = cat(3, A(:, :, :, iTime), zeros(nRows, nCols, 4));  % Pad with 4 empty slices
  C = mat2cell(C, nRows, nCols, ones(1, 25));  % Place each slice in a cell
  C = cell2mat(reshape(C, 5, 5).');            % Reshape cell array and make mosaic
  fileName = sprintf('%s_%d_.png', S.fileprefix, iTime);
  imwrite(C, fileName);
end

Upvotes: 1

Related Questions