How to preprocess NIfTI data format using NiBabel (Python) - python

after convertig a NIfTI-file to an array using NiBabel, the array has three dimensions and the numbers look like this:
[-9.35506855e-42 -1.78675141e-35 1.18329136e-30 -1.58892995e-24
5.25227377e-24 1.11677966e-23 -2.41237451e-24 -1.51333104e-25
6.79829196e-30 -9.84047188e-36 1.23314265e-43 -0.00000000e+00]
How can I preprocess this array for machine-learning? When choosing only the exponent, most of the information gets lost when plotting the image, so maybe the base is also important?
Any help is appreciated.

This will help you to convert a niftiimage to access as numpy array:
img = nib.load(example_filename)
data = img.get_fdata()

Related

Why does Nibabel change the size of my file?

I am working with images in the format nii.gz. Therefore, I am using nibabel in order to open them. The problem is that when I open the images, transform them to numpy arrays and convert them back to Nifti format, the output size is changed. The sequence is:
nifti_image = nib.load('/my_path_to_image/image.nii.gz')
np_img = ct_images.get_fdata()
nifti_final = nib.Nifti1Image(data, affine=np.eye(4)) # Convert them to nifti
nib.save(nifti_final , 'image.nii.gz')
The initial file is ~45 MB, after running the code above, the image is ~65 MB. I know that the original images are 16-bit encoded. My initial theory was that when transforming to numpy array, they were encoded as 64-bit which is indeed the case. So I tried the following:
nifti_image = nib.load('/my_path_to_image/image.nii.gz')
np_img = ct_images.get_fdata()
np_img = np_img.astype(numpy.float16, copy=False)
nifti_final = nib.Nifti1Image(data, affine=np.eye(4)) # Convert them to nifti
nib.save(nifti_final , 'image.nii.gz')
However, the ouput is still the same size ~65MB. Any ideas why this is happening?
You should add the original nifti affine and header information to the output nifti. E.g., in your case:
nifti_final = nib.Nifti1Image(data, nifti_image.affine, nifti_image.header)

convert tiff to netcdf

i try to convert a tiff to netcdf file. errors is saying index error:
import numpy as np
from netCDF4 import Dataset
import rasterio
with rasterio.drivers():
src=rasterio.open(r"ia.tiff","r")
dst_transform=src.transform
dst_width=src.width
dst_height=src.height
print (dst_transform)
xmin = dst_transform[0]
xmax = dst_transform[0] + dst_transform[1]*dst_width
print (xmax)
min = dst_transform[3] + dst_transform[5]*dst_height
print(ymin)
ymax = dst_transform[3]
dst_width=dst_width+1
dst_height=dst_height+1
outf=Dataset(r'ia.nc','w',format='NETCDF4_CLASSIC')
lats=np.linspace(ymin,ymax,dst_width)
lons=np.linspace(xmin,xmax,dst_height)
lat=outf.createDimension('lon',len(lats))
lon=outf.createDimension('lat',len(lons))
longitude=outf.createVariable('longitude',np.float64,('lon',))
latitude=outf.createVariable('latitude',np.float64,('lat',))
SHIA=outf.createVariable('SHIA',np.int8,('lon','lat'))
outf.variables['longitude'][:]=lons
outf.varibales['longitude'][:]=lat
im=src.read()
SHIA[:,:]=im
outf.description="IA for"
longitude.units="degrees east"
latitude.units='degrees north'
print ("created empty array")
outf.close()
outf.close()
error is that index error: size of the data array does not conform to slice. can somebody take a look and help me where i did wrong. Much appreciated!
I use xarray for this kind of things. Create xarray DataArray for each variable you have (seems SHIA for yours). Create DataSet and related DataArray with it. Don't forget to set coordinate variables into Dataset as coordinate.
see:
http://xarray.pydata.org/en/stable/io.html
Also you can convert your netcdf / tiff into dataframe and return again. But i wouldn't recommend this till you have to. Beause netcdf is multidimensional data and dataframe represent all data as cloning to one matrix.
The easiest way I could think of is to use the GDAL tool.
# Convert TIF to netCDF
gdal_translate -of netCDF -co "FOMRAT=NC4" ia.tif ia.nc
# Convert SHP to netCDF
gdal_rasterize -of netCDF -burn 1 -tr 0.01 0.01 input.shp output.nc

Image of Mnist data Python - Error when displaying the image

I'm working with the Mnist data set, in order to learn about Machine learning, and as for now I'm trying to display the first digit in the Mnist data set as an image, and I have encountered a problem.
I have a matrix with the dimensions 784x10000, where each column is a digit in the data set. I have created the matrix myself, because the Mnist data set came in the form of a text file, which in itself caused me quite a lot of problems, but that's a question for itself.
The MN_train matrix below, is my large 784x10000 matrix. So what I'm trying to do below, is to fill up a 28x28 matrix, in order to display my image.
import numpy as np
import matplotlib.pyplot as plt
import matplotlib.image as mpimg
grey = np.zeros(shape=(28,28))
k = 0
for l in range(28):
for p in range(28):
grey[p,l]=MN_train[k,0]
k = k + 1
print grey
plt.show(grey)
But when I try to display the image, I get the following error:
The truth value of an array with more than one element is ambiguous. Use a.any() or a.all()
Followed by a image plot that does not look like the number five, as I would expect.
Is there something I have overlooked, or does this tell me that my manipulation of the text file, in order to construct the MN_train matrix, has resulted in an error?
The error you get is because you supply the array to show. show accepts only a single boolean argument hold=True or False.
In order to create an image plot, you need to use imshow.
plt.imshow(grey)
plt.show() # <- no argument here
Also note that the loop is rather inefficient. You may just reshape the input column array.
The complete code would then look like
import numpy as np
import matplotlib.pyplot as plt
MN_train = np.loadtxt( ... )
grey = MN_train[:,0].reshape((28,28))
plt.imshow(grey)
plt.show()

How to convert (or scale) a FITS image with Astropy

Using the Astropy library, I created a FITS image which is made by interpolation from 2 actual FITS images (they are scaled as "int16", the right format for the software I use : Maxim DL).
But the scale of this image is float64 and not int16. And any astronomical processing software can't read it (except FITS Liberator)
Do you have an idea how to proceed ? Can we convert a FITS image just by changing the "BITPIX" in the header ?
I tried: (following this method : Why is an image containing integer data being converted unexpectedly to floats?
from astropy.io import fits
hdu1=fits.open('mypicture.fit')
image=hdu1[0]
print(image.header['BITPIX']) # it gives : -64
image.scale('int16')
data=image.data
data.dtype
print(image.header['BITPIX']) # it gives : 16
hdu1.close()
However, when I check the newly-modified scale of "mypicture.fit", it still displays -64 !
No change was saved and applied!
If I understand your problem correctly, this should work.
from astropy.io import fits
import numpy as np
# create dummy fits file
a = np.array([[1,2,3],
[4,5,6],
[7,8,9]],dtype=np.float64)
hdu = fits.PrimaryHDU()
hdu.data = a
# looking at the header object confirms BITPIX = -64
hdu.header
# change data type
hdu.data = np.int16(hdu.data)
# look again to confirm BITPIX = 16
hdu.header

How to reduce an image size in image processing (scipy/numpy/python)

Hello I have an image ( 1024 x 1024) and I used "fromfile" command in numpy to put every pixel of that image into a matrix.
How can I reduce the size of the image ( ex. to 512 x 512) by modify that matrix a?
a = numpy.fromfile(( - path - ,'uint8').reshape((1024,1024))
I have no idea how to modify the matrix a to reduce the size of the image. So if somebody has any idea, please share your knowledge and I will be appreciated. Thanks
EDIT:
When I look at the result, I found that the reader I got read the image and put it into a "matrix". So I changed the "array" to matrix.
Jose told me I can take only even column and even row and put it into a new matrix . That will reduce the image to half size. What command in scipy/numpy do I need to use to do that?
Thanks
If you want to resize to specific resolution, use scipy.misc.imresize:
import scipy.misc
i_width = 640
i_height = 480
scipy.misc.imresize(original_image, (i_height, i_width))
Use the zoom function from scipy:
http://docs.scipy.org/doc/scipy/reference/generated/scipy.ndimage.zoom.html#scipy.ndimage.zoom
from scipy.ndimage.interpolation import zoom
a = np.ones((1024, 1024))
small_a = zoom(a, 0.5)
I think the easyiest way is to take only some columns and some rows of the image. Makeing a sample of the array. Take for example, only those even rows and the even columns, put it in a new array and you would have a half size new image.

Categories