How to convert exported vtk image to numpy array? - python

Here's the code:
'''
import vtk
import numpy as np
from vtk.util.numpy_support import vtk_to_numpy
# Load the data
reader = vtk.vtkXMLImageDataReader()
reader.SetFileName("Isabel_2D.vti")
reader.Update()
imageData = reader.GetOutput() #read data
# Export the data to a buffer
exporter = vtk.vtkImageExport()
exporter.SetInputData(imageData)
exporter.Update()
data_pointer = exporter.GetPointerToData().GetScalars()
# Get the image data as a numpy array
#imageDataArray = np.frombuffer(data_pointer, np.float32) #.encode()
#imageDataArray = imageDataArray.reshape(imageData.GetDimensions())
rows, cols, _ = exporter.GetDimensions()
imageDataArray = vtk_to_numpy(sc)
imageDataArray = imageDataArray.reshape(rows, cols, -1)
'''
How to resolve the following error :
AttributeError: 'str' object has no attribute 'GetScalars'

You do not need the exporter part.
You should get the desired array from the imageData (GetPointData().GetScalars()) and wrap it. See this same post on vtk forum.

Related

Unable to write Raster using Gdal in Python. Error:dict' object has no attribute 'shape'

I am trying to create a raster file after filling NO DATA with some value using gdal in Python.
I have a function that gets me the raster array.
def raster2array(rasterfn):
try:
bndNum_Val_Dic={}
raster = gdal.Open(rasterfn)
for bandNum in range(raster.RasterCount):
bandNum += 1
band=raster.GetRasterBand(bandNum)
bandVal=band.ReadAsArray()
bndNum_Val_Dic[bandNum]=bandVal
raster=None
return bndNum_Val_Dic
except Exception as e:
print(e)
Using the array generated from from this function I am trying to write my raster which throws an error at "outband.WriteArray(array)" that dict' object has no attribute 'shape'.
import numpy as np
import gdal
from osgeo import osr
rasterfn ="MAH_20.tif"
newRasterfn ="MAH_FND.tif"
array= raster2array(rasterfn)
newValue = 100
Driver= 'GTiff'
bandNumber=1
raster = gdal.Open(rasterfn)
geotransform = raster.GetGeoTransform()
originX = geotransform[0]
originY = geotransform[3]
pixelWidth = geotransform[1]
pixelHeight = geotransform[5]
cols = raster.RasterXSize
rows = raster.RasterYSize
bandCount=raster.RasterCount
rasterDataType=raster.GetRasterBand(bandNumber).DataType
global Flag
if(Flag):
driver = gdal.GetDriverByName(Driver)
global outRaster
outRaster = driver.Create(newRasterfn, cols, rows, bandCount, rasterDataType)
Flag=False
outband = outRaster.GetRasterBand(bandNumber)
outRaster.SetGeoTransform((originX, pixelWidth, 0, originY, 0, pixelHeight))
outband = outRaster.GetRasterBand(bandNumber)
outband.WriteArray(array)
outRasterSRS = osr.SpatialReference()
outRasterSRS.ImportFromWkt(raster.GetProjectionRef())
outRaster.SetProjection(outRasterSRS.ExportToWkt())
outRaster.GetRasterBand(bandNumber).SetNoDataValue(newValue)
raster=None
if(bandNumber==bandCount):
outRaster=None
outband=None
raster=None
I am using python 3.5 and GDAL 3.0.2. Is there any way to fix this?
Any help will be appreciated
You are trying two write a dictionary while GDAL expects a Numpy array. It's not completely clear which data you are trying to write, but changing your write statement to something as shown below should at least get rid of the error message. But make sure you write the correct band.
outband.WriteArray(array[bandNumber])

From numpy array to DICOM

My code reads a DICOM file, takes the pixel information to a numpy array then it modifies the numpy array. It uses lists because im trying to operate with multiple DICOM files at the same time.
I havent found any information on how to take my modified numpy array and make it a DICOM file again so i can use it outside Python.
#IMPORT
import cv2
import numpy as np
from matplotlib import pyplot as plt
import matplotlib.pyplot as plt
import SimpleITK as sitk
from glob import glob
import pydicom as dicom
data_path = "C:\\Users\\oliva\\Desktop\\Py tesis\\dicom\\"
output_path = working_path = "C:\\Users\\oliva\\Desktop\\Py tesis\\dicom1\\"
path = glob(data_path + '/*.dcm')
#Checks if we are in the correct path
print ("Total of %d DICOM images.\nFirst 5 filenames:" % len(path))
print ('\n'.join(path[:14]))
data_set = []
for element in path:
imagen=sitk.ReadImage(element)
#imagen = cv2.imread(element)
array_imagen = sitk.GetArrayViewFromImage(imagen)
array2_imagen=array_imagen[0]
imagen_array_norm = np.uint8(cv2.normalize(array2_imagen, None, 0, 255, cv2.NORM_MINMAX))
data_set.append(imagen_array_norm)
#Check
print(len(data_set))
print(type(data_set[1]))
plt.imshow(data_set[4], cmap=plt.cm.gray)
#Equalization
data_set_eq = equal(data_set)
print(len(data_set_eq))
print(type(data_set_eq[6]))
plt.imshow(data_set_eq[7], cmap=plt.cm.gray)
#Filtering
data_set_m = median(data_set)
print(len(data_set_m))
print(type(data_set_m[6]))
plt.imshow(data_set_m[8], cmap=plt.cm.gray)
#Functions
def equal(data):
data_set_eq = []
for element in data_set:
imagen_array_eq = cv2.equalizeHist(element)
data_set_eq.append(imagen_array_eq)
return data_set_eq
def median(data):
data_set_m = []
for element in data_set:
imagen_array_m =cv2.medianBlur(element,5)
data_set_m.append(imagen_array_m)
return data_set_m
I would like some enlightenment on how to produce a DICOM file from my modified numpy array.
You can convert the numpy array back to a SimpleITK image, and then write it out as Dicom. The code would look something like this:
for x in data_set:
img = sitk.GetImageFromArray(x)
sitk.WriteImage(img, "your_image_name_here.dcm")
From the file name suffix, SimpleITK knows to write Dicom.
Note that the filtering you are doing can be accomplished within SimpleITK. You don't really need to use OpenCV. Check out the following filters in SimpleITK: IntensityWindowingImageFilter, AdaptiveHistogramEqualizationFilter, and MedianImageFilter.
https://itk.org/SimpleITKDoxygen/html/classitk_1_1simple_1_1IntensityWindowingImageFilter.html
https://itk.org/SimpleITKDoxygen/html/classitk_1_1simple_1_1AdaptiveHistogramEqualizationImageFilter.html
https://itk.org/SimpleITKDoxygen/html/classitk_1_1simple_1_1MedianImageFilter.html

How to create a TFRecord from a NumPy array

I'd like to 1. iterate through a directory of images and turn each image into a NumPy array. I think I have accomplished this with the following code:
import tensorflow as tf
import matplotlib
matplotlib.use('TkAgg')
import matplotlib.pyplot as plt
import matplotlib.image as mpimg
import numpy as np
from PIL import Image
import os
myimages = []
path_to_images = 'images_animation'
filenum = len([name for name in os.listdir(path_to_images) if os.path.isfile(os.path.join(path_to_images, name))])
#loops through available pngs
for p in range(1, filenum):
## Read in picture
fname = "images_animation/image%03d.png" % p
img = mpimg.imread(fname)
imgplot = plt.imshow(img)
# append AxesImage object to the list
myimages.append([imgplot])
for n, im in enumerate(myimages):
img = Image.open(fname).convert("L")
arr = np.array(img
print(arr)
If I can make this code better or more efficient, please feel free to tell me how.
Now, I'd like to 2. turn these NumPy arrays into TFRecords. What is the best way to do so? I'm near clueless as how to do this, so I have not done much to solve it myself, so I'm looking for a solution.

How do I import tif using gdal?

How do I import tif using gdal?
I'm trying to get my tif file in a usable format in Python, so I can analyze the data. However, every time I import it, I just get an empty list. Here's my code:
xValues = [447520.0, 432524.0, 451503.0]
yValues = [4631976.0, 4608827.0, 4648114.0]
gdal.AllRegister()
dataset = gdal.Open('final_snow.tif', GA_ReadOnly)
if dataset is None:
print 'Could not open image'
sys.exit(1)
data = np.array([gdal.Open(name, gdalconst.GA_ReadOnly).ReadAsArray() for name, descr in dataset.GetSubDatasets()])
print 'this is data ', data`
It always prints an empty list, but it doesn't throw an error. I checked out other questions, such as [this] (Create shapefile from tif file using GDAL) What might be the problem?
For osgeo.gdal, it should look like this:
from osgeo import gdal
gdal.UseExceptions() # not required, but a good idea
dataset = gdal.Open('final_snow.tif', gdal.GA_ReadOnly)
data = dataset.ReadAsArray()
Where data is either a 2D array for 1-banded rasters, or a 3D array for multiband.
An alternative with rasterio looks like:
import rasterio
with rasterio.open('final_snow.tif', 'r') as r:
data = r.read()
Where data is always a 3D array, with the first dimension as band index.

How to convert a vtkimage into a numpy array

I tried to deal with MHD image files with python and python-vtk. The file is placed in google drive : mhd . I want to convert it into numpy array and then split them according to a given value' 500 for instance '. then calculate the summary information. I followed the instruction of this [post] How to convert a 3D vtkDataSet into a numpy array? but it does not work for my case.
import vtk
imageReader = vtk.vtkMetaImageReader()
imageReader.SetFileName(testfile1)
imageReader.Update()
# from vtk.util.numpy_support import numpy_to_vtk, vtk_to_numpy does not work for the data type issue
image = imageReader.GetOutput()
# List the dimensions of the image, for example
print image.GetDimensions()
pixelspace = imageReader.GetPixelSpacing()
an error comes here:
AttributeError: GetPixelSpacing
How could I achieve the conversion?
When I finish the data splitting, how could I save them back to mhd (or a raw data would be better ?)
Adapting from this thread... you can do the following:
import numpy as np
import vtk
from vtk.util.numpy_support import vtk_to_numpy
imr = vtk.vtkMetaImageReader()
imr.SetFileName('t10-Subvolume-resample_scale-1.mhd')
imr.Update()
im = imr.GetOutput()
rows, cols, _ = im.GetDimensions()
sc = im.GetPointData().GetScalars()
a = vtk_to_numpy(sc)
a = a.reshape(rows, cols, -1)
assert a.shape==im.GetDimensions()
where a will be a NumPy array containing the image data.
To get the channels right for later use as OpenCV image:
import vtk
import numpy as np
from vtk.util import numpy_support
def vtkImgToNumpyArray(vtkImageData):
rows, cols, _ = vtkImageData.GetDimensions()
scalars = vtkImageData.GetPointData().GetScalars()
resultingNumpyArray = numpy_support.vtk_to_numpy(scalars)
resultingNumpyArray = resultingNumpyArray.reshape(cols, rows, -1)
red, green, blue, alpha = np.dsplit(resultingNumpyArray, resultingNumpyArray.shape[-1])
resultingNumpyArray = np.stack([blue, green, red, alpha], 2).squeeze()
resultingNumpyArray = np.flip(resultingNumpyArray, 0)
return resultingNumpyArray

Categories