Separating "Binary" Masks Into Separate Files

8 views (last 30 days)
Rowan Lawrence
Rowan Lawrence on 21 Jun 2023
Edited: Siraj on 23 Aug 2023
Hello! I have a number of participants each of which have binary masks in NIFTI / .nii files for 14 different brain structures in each hemisphere of the brain (6 in each hemisphere). The masks for the structures in the left hemisphere have the values [2, 4, 6, 8, 10, 12, 14] and the corresponding right-hemisphere masks have the values [1, 3, 5, 7, 9, 11, 13]. Voxels in the rest of the volume have the value 0.
I'd like to separate the masks for the left- and right-hemisphere structures into two separate files, i.e., all of the even-value masks for that participant into one .nii file and all of the odd-value masks into another. I haven't scripted anything in MATLAB for a long time and am not sure on the best way to go about this. (I do also have the SPM toolbox available, in case the best solution is using imcalc or something similar.)
Thank you for any help!
Edit:
I have tried this in what I thought would be the most straightforward way possible:
left_values = [2, 4, 6, 8, 10, 12, 14];
right_values = [1, 3, 5, 7, 9, 11, 13];
ROI_path = fullfile('F:', 'WT', 'Imaging', 'ROI', 'Aligned', 'Controls', 'CON_L01_MALPEM_MTL_T1ALIGNED.nii');
vol = niftiread(ROI_path);
indices_left = ismember(vol, left_values);
indices_right = ismember(vol, right_values);
ROIs_left = find(indices_left);
ROIs_right = find(indices_right);
vol_left = vol(ROIs_left > 0);
vol_right = vol(ROIs_right > 0);
The vol is 288x195x288, but the ROI_left/vol_left and ROI_right/vol_right variables are 18267x1 and 16167x1, respectively, which is not the same number of elements as the original image. I assume these are just the voxels that were in the original masks, but I need to maintain the zeroes and overall structure of the mask image. I'm a little confused on where to go from here!
Edit 2:
Since the 0's also need to be included in each of the output masks, I tried adding zeroes to each of the target values lists. Then, after finding the indices of the left- and right-hemisphere masks, I just set these to 0 in the output volume for the opposite hemisphere:
left_values = [0, 2, 4, 6, 8, 10, 12, 14];
right_values = [0, 1, 3, 5, 7, 9, 11, 13];
ROI_path = fullfile('F:', 'WT', 'Imaging', 'ROI', 'Aligned', 'Controls', 'CON_L01_MALPEM_MTL_T1ALIGNED.nii');
out_path = fullfile('F:', 'WT', 'Radiomics', 'TestOut.nii');
vol = niftiread(ROI_path);
expected = size(vol, 1) * size(vol, 2) * size(vol, 3);
indices_left = ismember(vol, left_values);
indices_right = ismember(vol, right_values);
vol_left = vol;
vol_right = vol;
vol_left(indices_right) = 0;
vol_right(indices_left) = 0;
niftiwrite(vol_left, out_path);
This works as expected, which I'm happy with, though would be grateful for any comments on the above and if this is the cleanest / most efficient way of achieving it!

Answers (1)

Siraj
Siraj on 22 Aug 2023
Edited: Siraj on 23 Aug 2023
Hii! @Rowan Lawrence it is my understanding that you have a 3d array (vol) with pixel values from 0 to 14. The task is to partition this array into 2 arrays with the exact same shape as the original array. The vol_left array should only contain even values and the vol_right array should only contain odd values.
The main issue with the first approach is that it flattens the arrays, therefore the vol_left and vol_right are 1d arrays, which I guess is undesired.
The second approach is works alright but can be optimized as follows.
vol = randi([0, 14], 3, 3, 3); %don't have the data so generated a random matrix of shape 3X3X3.
evenPixels = mod(vol, 2) == 0; %creates a logical mask where true represents even pixel values.
vol_left = vol;
vol_left(evenPixels == 0) = 0; % all the odd values are set 0;
vol_right = vol - vol_left; % this would remove all the even pixels from vol and will keep 0 unaffected.
display(vol);
vol =
vol(:,:,1) = 4 2 4 2 7 7 1 5 7 vol(:,:,2) = 4 6 6 5 1 4 12 0 12 vol(:,:,3) = 10 2 6 3 11 11 5 12 2
display(vol_left);
vol_left =
vol_left(:,:,1) = 4 2 4 2 0 0 0 0 0 vol_left(:,:,2) = 4 6 6 0 0 4 12 0 12 vol_left(:,:,3) = 10 2 6 0 0 0 0 12 2
display(vol_right);
vol_right =
vol_right(:,:,1) = 0 0 0 0 7 7 1 5 7 vol_right(:,:,2) = 0 0 0 5 1 0 0 0 0 vol_right(:,:,3) = 0 0 0 3 11 11 5 0 0
Next, we can save the vol_left and vol_right in the desired output location.
Please refer to the documentation for further details on indexing arrays with logical values.
Hope this helps.

Products


Release

R2022b

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!