简体   繁体   中英

change voxel values in nifti image and save it

I am going to read a nifti image and change the values of the voxels and save the new nifti image similar to the main image but only different voxel values. In other words I want my labels in segmentation image be from 0 to 7 instead of having different numbers. o wrote the code below but I get this error:

NotImplementedError: Wrong number or type of arguments for overloaded function 'WriteImage'.

Possible C/C++ prototypes are: itk::simple::WriteImage(itk::simple::Image const &,std::string const &,bool) itk::simple::WriteImage(itk::simple::Image const &,std::vector< std::string,std::allocator< std::string > > const &,bool)

The code:

for image_path in os.listdir(path):

label_name = os.path.join(path, image_path)

img = nib.load(label_name)
data = img.get_fdata()
n=0;
u=0;
m=0;
b=0;
e=0;
r=0;
s=0;
img1=img
data1 = img1.get_fdata()
for i in range (0,img.shape[0]):
    for j in range (0,img.shape[1]):
        for k in range (0,img.shape[2]):

            if data[i,j,k]==500:
                n=n+1;
                data1[i,j,k]=1;
            elif data[i,j,k]==600:
                u=u+1;
                data1[i,j,k]=2;
            elif data[i,j,k]==420:
                b=b+1;
                data1[i,j,k]=3;
            elif data[i,j,k]==550:
                e=e+1;
                data1[i,j,k]=4;
            elif data[i,j,k]==205:
                r=r+1;
                data1[i,j,k]=5;
            elif data[i,j,k]==820:
                m=m+1;
                data1[i,j,k]=6;
            elif data[i,j,k]==850:
                s=s+1;
                data1[i,j,k]=7



OUTPUT_DIR='/Volumes/CSE_BME_AXM788/home/gxa131/labelsTr_new/'  
dir1=os.path.join(OUTPUT_DIR, image_path)
sitk.WriteImage(data1,dir1)

SimpleITK's WriteImage function is expecting a SimpleITK Image for the first argument. The get_fdata method for an NiBabel Image returns a Numpy array. If you want to use SimpleITK to write the image, you need to convert from Numpy to SimpleITK using the GetImageFromArray function.

Note that you will lose any meta-data information that came with the original image such as pixel spacing.

UPDATE:

To answer your question about preserving the meta data:

I haven't used NiBabel myself, but the following page describes how to create a new image from a data array, copying over the header information from the original image: https://bic-berkeley.github.io/psych-214-fall-2016/saving_images.html

I would use SimpleITK for the entire process myself. If you load the image using SimpleITK and do all your processing on a SimpleITK Image object, all the meta data is preserved.

And for your particular code, you can use the RelabelLabelMapFilter class to map your original labels (500, 600, 520, 550, 205, 820, 850) to (1-7), assuming those are the only labels. That way you don't have to loop through all the voxels yourself. https://simpleitk.org/doxygen/latest/html/classitk_1_1simple_1_1RelabelLabelMapFilter.html#details

And to count the number of voxels for each label, you can use the LabelShapeStatisticsImageFilter. Again, this avoids looping through the voxels by hand: https://simpleitk.org/doxygen/latest/html/classitk_1_1simple_1_1LabelShapeStatisticsImageFilter.html

In order to save the meta data, use nibabel.save as the example below:

new_nifti = nib.Nifti1Image(***numpy_arrray***.astype(np.float), nii_original_scan.affine)
nib.save(new_nifti, f'***path to new scan***.nii.gz')

Explanation: You should save the new NIfTI scan (NumPy array) as nii image. In order to do it, use Nifti1Image to create nii object, and then nibabel.save to save it to a file.

Numpy_array argument- is your numpy array (make sure is in float type). The second argument is the original NIfTI scan after loading (with affine function).

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM