Converting VTK image (.vti) data to VTK poly (.vtp) data - python

I'm trying to take some VTK image data generated from a 3-D numpy array and convert it into poly data so it can be read by a package that only takes .vtp as an input format. I chose to use the marching cubes algorithm to take my point/node data as input and give poly data as an output. The data is segmented into two phases (0 = black, 255 = white), so only one contour is necessary. I tried using the vtkPolyDataReader class to create an object for the vtkMarchingCubes class, then using vtkPolyDataWriter to take the contoured marching cubes object and save it as a VTP file:
import vtk
input = 'mydata.vti'
reader = vtk.vtkPolydataReader()
reader.SetFileName(input)
reader.Update()
contour = vtk.vtkMarchingCubes()
contour.SetInputConnection(reader.GetOutputPort())
contour.SetValue(0, 128.)
contour.Update()
writer = vtk.vtkPolyDataWriter()
writer.SetInputData(contour.GetOutput())
writer.SetFileName('mydata.vtp')
writer.Update()
writer.Write()
When I run the code, it takes much less time than it ought to (the input file is about 2 GB), and the VTP file the code creates is less than 1 KB. I've been banging my head against a wall over this and poring over the VTK documentation and some provided examples, but I can't figure out what I've done wrong.

To read a .vtki file you need to use vtk.vtkXMLImageDataReader. You are trying to read an image file with a vtk.vtkPolyDataReader, which is designed for reading surface meshes.

Related

save and write a .vtk polydata file

I used this puyhon code to convert nifti file to .vtk polydata meshes
import itk
import vtk
input_filename = '/home/nour/Bureau/7ans/244/whatIneed/244seg_pve_2.nii.gz'
reader=itk.ImageFileReader[itk.Image[itk.UC,3]].New()
reader.SetFileName(input_filename)
reader.Update()
itkToVtkFilter = itk.ImageToVTKImageFilter[itk.Image[itk.UC,3]].New()
itkToVtkFilter.SetInput(reader.GetOutput())
myvtkImageData = itkToVtkFilter.GetOutput()
print("myvtkImageData")
and for saving and writing the .vtk file I used
writer = vtk.vtkPolyDataWriter()
writer.SetInputData()
writer.SetFileName("/home/nour/Bureau/7ans/244/whatIneed/Output.vtk")
writer.Write()
and here the error :
ERROR: In /work/standalone-x64-build/VTK-source/Common/ExecutionModel/vtkDemandDrivenPipeline.cxx, line 809
vtkCompositeDataPipeline (0x4d9cac0): Input for connection index 0 on input port index 0 for algorithm vtkPolyDataWriter(0x4de3ea0) is of type vtkImageData, but a vtkPolyData is required.
I was wondering as to what would be a good way of writing a vtk Polydata file.
thanks
You need to transform your image (regular grid) into a polygonal mesh to be able to save it as a .vtk file.
For 2D meshes, this can be done using the vtkExtractSurface filter.
Another solution would be to use another format (.vtk is a legacy format):
If you want to save a regular grid, you can use the vtkXMLImageDataWriter, that uses the .vti extension.
If you want a unstructured mesh, you can use the vtkXMLPolyDataWriter, that uses the .vtp extension and gives a polygonal mesh. You can also use the vtkXMLUnstructuredGridWriter, that uses the .vtu extension and can contain 3D cells.
Images and polygonal meshes are fundamentally different types of data. You can't just cast an image into a mesh.
To get a mesh you would need to do some type of iso-surface extraction. Typically you would select some image intensity as the value of your surface, and then you would use an algorithm such as Marching Cubes to create a mesh of that value.
In VTK you can use the vtkContourFilter to create a mesh from an image. There are a number of examples on the VTK Example web site that show how to use the filter. Here is one:
https://lorensen.github.io/VTKExamples/site/Python/ImplicitFunctions/Sphere/
thank you very much. So as I understand :
1 reading nifti file (segmented file)
2 apply itktovtkfilter
3 creating meshes (using the vtkContourFilter)
4 and finaly convert it to polydata and save it to .vtk file
that's right ??

How can I cut a portion of a satellite image based on coordinates? (gdal)

I have a satellite image of 7-channels (Basically I have seven .tif files, one for each band). And I have a .csv file with coordinates of points-of-interest that are in the region shot by the satellite. I want to cut small portions of the image in the surroundings of each coordinate point. How could I do that?
As I don't have a full working code right now, it really doesn't matter the size of those small portions of image. For the explanation of this question let's say that I want them to be 15x15 pixels. So for the moment, my final objective is to obtain a lot of 15x15x7 vectors, one for every coordinate point that I have in the .csv file. And that is what I am stucked with. (the "7" in the "15x15x7" is because the image has 7 channels)
Just to give some background in case it's relevant: I will use those vectors later to train a CNN model in keras.
This is what I did so far: (I am using jupyter notebook, anaconda environment)
imported gdal, numpy, matplotlib, geopandas, among other libraries.
Opened the .gif files using gdal, converted them into arrays
Opened the .csv file using pandas.
Created a numpy array called "imagen" of shape (7931, 7901, 3) that will host the 7 bands of the satellite image (in form of numbers). At this point I just need to know which rows and colums of the array "imagen" correspond to each coordinate point. In other words I need to convert every coordinate point into a pair of numbers (row,colum). And that is what I am stucked with.
After that, I think that the "cutting part" will be easy.
#I import libraries
from osgeo import gdal_array
import numpy as np
import matplotlib.pyplot as plt
import pandas as pd
import geopandas
from geopandas import GeoDataFrame
from shapely.geometry import Point
#I access the satellite images (I just show one here to make it short)
b1 = r"E:\Imágenes Satelitales\2017\226_86\1\LC08_L1TP_226086_20170116_20170311_01_T1_sr_band1.tif"
band1 = gdal.Open(b1, gdal.GA_ReadOnly)
#I open the .csv file
file_svc = "C:\\Users\\Administrador\Desktop\DeepLearningInternship\Crop Yield Prediction\Crop Type Classification model - CNN\First\T28_Pringles4.csv"
df = pd.read_csv(file_svc)
print(df.head())
That prints something like this:
Lat1 Long1 CropingState
-37.75737 -61.14537 Barbecho
-37.78152 -61.15872 Verdeo invierno
-37.78248 -61.17755 Barbecho
-37.78018 -61.17357 Campo natural
-37.78850 -61.18501 Campo natural
#I create the array "imagen" (I only show one channel here to make it short)
imagen = (np.zeros(7931*7901*7, dtype = np.float32)).reshape(7931,7901,7)
imagen[:,:,0] = band1.ReadAsArray().astype(np.float32)
#And then I can plot it:
plt.imshow(imagen[:,:,0], cmap = 'hot')
plt.plot()
Which plots something like this:
(https://github.com/jamesluc007/DeepLearningInternship/blob/master/Crop%20Yield%20Prediction/Crop%20Type%20Classification%20model%20-%20CNN/First/red_band.png)
I want to transform those (-37,-61) into something like (2230,1750). But I haven't figured it how yet. Any clues?

Python Increasing Resolution of Converting from Numpy Array to Image using Matplotlib and PIL

I'm currently using Python 3.7.3 on Linux CentOS 7. I am conducting research related to NASA's THEMIS All-Sky-Imager (ASI) database, where I attempt to extract auroral images (keograms) from the .cdf files (which describe visual information for each auroral epoch in the form of a NumPy array). I convert the NumPy array to 'approximately' its corresponding image using Matplotlib and PIL (Python Imaging Library) in the following code:
I would like to note that I'm using the Python3 console within the Linux terminal. Also, I am using the SpacePy Library to read the .cdf file using the pycdf.CDF(...) function.
# Define .cdf file object as downloaded from NASA THEMIS ASI Database
>>> cdf = pycdf.CDF('/projectnb/burbsp/big/SATELLITE/themis/data/thg/l1/asi/gill/2008/01/thg_l1_asf_gill_2008011403_v01.cdf')
# Display .cdf file objects; 'thg_asf_gill' defines the set of arrays which contains the visual information stored for each image; i.e. cdf['thg_asf_gill'][0,:,:] would define the first epoch array up to cdf['thg_asf_gill'][1197,:,:] which is the last epoch array (a total 1198 epoch arrays).
>>> print(cdf)
range_epoch: CDF_EPOCH [2]
thg_asf_gill: CDF_UINT2 [1198, 256, 256]
thg_asf_gill_column: CDF_UINT2 [256] NRV
thg_asf_gill_epoch: CDF_EPOCH [1198]
thg_asf_gill_epoch0: CDF_EPOCH [] NRV
thg_asf_gill_row: CDF_UINT2 [256] NRV
thg_asf_gill_tend: CDF_REAL8 [1198]
thg_asf_gill_time: CDF_REAL8 [1198]
Then, I use what I've seen suggested on stack overflow to convert the NumPy array (take the last epoch array as an example) into an image plot.
>>> pyplot.imshow(cdf['thg_asf_gill'][1197,:,:])
>>> pyplot.show()
The resulting image (Image Plot of Aurora) can be found below:
As you can see there are some features that aren't shown because they are a bit too dim, so I tried to play around with the color scaling using the following:
pyplot.clim(vmin,vmax)
Where vmin and vmax are some values; in particular I use vmin = 5000 and vmax = 10000 (I also played around with other values), the resulting image (Altered Image Plot of Aurora) is:
The image becomes too distorted (resolution-wise).
The NASA THEMIS ASI image is found below:
As you can see, the image yielded from PIL and Matplotlib is somewhat of a transormation/rotation of the actual NASA image. Also, the dim-ish features are lost. So, what's a way to increase the resolution of the resultant image such that the the bright features don't become too bright/distorted (as seen from the altered image) and the dim features are enhanced?
Thank you!

Is there any way to read one image row/column into an array in Python?

I've just translated some CT reconstruction software from IDL into Python, and this is my first experience ever with Python. The code works fine except that it's much, much slower. This is due, in part, to the fact that IDL allows me to save memory and time by reading in just one row of an image at a time, using the following:
image = read_tiff(filename, sub_rect = [0, slice, x, 1])
I need to read one row each from 1800 different projection images, but as far as I can tell I can only create an image array by reading in the entire image and then converting it to an array. Is there any trick to just read in one row from the start, since I don't need the other 2047 rows?
It looks like tifffile.py by Christoph Gohlke (http://www.lfd.uci.edu/~gohlke/code/tifffile.py.html) can do the job.
from tiffile import TiffFile
with TiffFile('test.tiff') as tif:
for page in tif:
image = page.asarray(memmap=True)
print image[0,:,:]
If I interpret the code correctly this will extract the first row of every page in the file without loading the whole file into memory (through numpy.memmap).

Reading ascii vtk file in python and converting it to numpy array

I have a vtk file that contains UNSTRUCTURED POINTS datasets. It has several datasets inside (fields, currents, densities).
I would like to load this file in python and convert every dataset to the numpy array to plot it with matplotlib. How to do this?
Without having an example of your file, it's hard to give a precise answer. But from what I know about vtk files, they can contain either ASCII or binary data after a 4 line header.
If the data in the vtk is ASCII, then
np.loadtxt(filename, skiplines=4)
should work. Again, the structure of your file could make this tricky if you have a bunch of different fields.
If the data is in binary, you will need to use something like
filename.read()
struct.unpack()
or
np.fromfile()
The solution is given by vtk_to_numpy function from the VTK package. It is used along a Vtk grid reader depending on the grid format (structured or unstructured): vtkXMLUnstructuredGridReader is a good choice in your case.
A sample code would look like:
from vtk import *
from vtk.util.numpy_support import vtk_to_numpy
# load a vtk file as input
reader = vtk.vtkXMLUnstructuredGridReader()
reader.SetFileName("my_input_data.vtk")
reader.Update()
#The "Temperature" field is the third scalar in my vtk file
temperature_vtk_array = reader.GetOutput().GetPointData().GetArray(3)
#Get the coordinates of the nodes and their temperatures
nodes_nummpy_array = vtk_to_numpy(nodes_vtk_array)
temperature_numpy_array = vtk_to_numpy(temperature_vtk_array)
x,y,z= nodes_nummpy_array[:,0] ,
nodes_nummpy_array[:,1] ,
nodes_nummpy_array[:,2]
(...continue with matplotlib)
A longer version with matplotib plotting can be found in this thread: VTK to Maplotlib using Numpy

Categories

Resources