How to obtain the centroid of cells/elements in VTK? - python

I know how to get the coordinates of the points in an unstructured grid from this post: vtk to matplotlib using numpy
However, I am trying to find a function that takes the unstructured VTK grid and returns the coordinates of the "centers" of the cells/elements. In particular, I'm working with a cylinder composed of quad elements. Here's the code I have so far:
from srlife import writers #library that helps make vtk grid
import numpy as np
import vtk
from vtk.util.numpy_support import vtk_to_numpy
vtkTube1 = writers.VTKWriter(tube1, 'tube1.vtk')
grid = vtk.vtkUnstructuredGrid()
points = vtk.vtkPoints()
for x,y,z in zip(X.flatten(), Y.flatten(), Z.flatten()):
points.InsertNextPoint(x,y,z)
grid.SetPoints(points)
vtkTube1._set_grid(grid)
getCellLocations = vtk_to_numpy(grid.GetCellLocationsArray()) #this just returns 1D array of integers that I don't know what to do with
I tried looking into meshio and griddata from scipy.interpolate but the documentation wasn't very helpful.

GetCellLocationsArray does not return geometrical information (see doc) but the indices of the beginning of each cell in the cell array returned by GetCells
You can try the vtkCellCenters filter.
Note: doc is C++ but python API is really similar.

Related

How to display, update and rotate 3d points with color in python?

I have a ply file with x,y,z and R,G,B components. What is the best way to display it in python?
To display and rotate .ply with python you can try this function
import numpy as np
import open3d as o3d
def open_3Dfile(input_file):
# Read .ply file
pcd = o3d.io.read_point_cloud(input_file) # Read the point cloud
# Visualize the point cloud within open3d
o3d.visualization.draw_geometries([pcd])
# Convert open3d format to numpy array
# Here, you have the point cloud in numpy format.
point_cloud_in_numpy = np.asarray(pcd.points)
input_file = 'example.ply'
open3Dfile(input_file)

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?

VTK vtkDataSet to 3D numpy array and back

I'm moving my first steps into vtk and I'm quite struggling given the lack of documentation.
I've got a .vtk file which is a vtkDataSet type object I haven't created. I would need to export the content of it and convert it to a 3D numpy matrix, customise it and its tensor and write everything in a vtkDataSet object and .vtk file.
What I've ended up so far is save the coordinates, which is not what I need, of the points into a numpy array using vtk.util.numpy_support vtk_to_numpy. However, I'd need a 3D numpy matrix representing the volume rendering of it.
Speaking about the tensor, I figured out how and where to save my 9-elements tensor into the file. I'm just not sure on how to set it properly to be related to the points.
The last step, which is 3D numpy array to vtk, looks feasible using numpy.ravel and numpy_to_vtk from vtk.util.numpy_support.
Here's some code I'm using as a test:
# reader for mrtrix vtk file
reader = vtk.vtkDataSetReader()
file_name = 'my_file.vtk'
reader.SetFileName(file_name)
reader.Update()
# get the vtkDataArray
data_set = reader.GetOutput()
# these are the coordinates of the points
# I'd need the 3D numpy volume rendering matrix instead
point_array = data_set.GetPoints().GetData()
# test tensor
# I'd need to save a tensor for every element of the 3D numpy matrix
tensor = numpy_to_vtk(np.zeros([data_set.GetNumberOfPoints(), 9]))
tensor.SetName('Tensors_')
point_data = data_set.GetPointData()
point_data.SetAttribute(tensor, 4)
This may be useful in your case:
https://github.com/marcomusy/vedo/blob/master/vedo/examples/volumetric/numpy2volume1.py
and retrieve the numpy object with e.g.
print('numpy array from Volume:', vol.getPointArray().shape)

Plot 3d volumetric data represented by a 3D numpy array

I've seen that vtkplotter supports a wide range of volumetric image formats, but does it support plotting numpy arrays? I have an image in a .mhd format that I converted to .npz file and would like to plot it using the mentioned library. Is there a way to do so?
import numpy as np
data = np.zeros((3,3,3))
# how to plot this?
If you know any other tools for visualizing volumetric data, suited for medical analysis, please tell so. I've tried mayavi but it consumes so much memory that it crashes my computer.
You can use numpy_support to convert numpy arrays to vtkImageData (i.e. a VTK 3D image).
An example follows, there's a numpy warning about type conversion: I don't think it's relevant but I'm not a python guru...
from vtk.util import numpy_support
import vtk
import numpy as np
data = np.zeros((3,3,3))
# vtkImageData is the vtk image volume type
imdata = vtk.vtkImageData()
# this is where the conversion happens
depthArray = numpy_support.numpy_to_vtk(data.ravel(), deep=True, array_type=vtk.VTK_DOUBLE)
# fill the vtk image data object
imdata.SetDimensions(data.shape)
imdata.SetSpacing([1,1,1])
imdata.SetOrigin([0,0,0])
imdata.GetPointData().SetScalars(depthArray)
# f.ex. save it as mhd file
writer = vtk.vtkMetaImageWriter()
writer.SetFileName("test.mhd")
writer.SetInputData(imdata)
writer.Write()
... and to visualize vtk volume data you can use Paraview.

Plotting two images side by side in python

I'd like to plot two images side by side in Python using matplotlib. However I don't want to create separate subplots. I want to plot two images in the same figure so that I can draw correspondences between the two images. See image below.
In Matlab I believe this can be done using imshow([I1, I2]) however the python API for matplotlib does not accept an array of images. Is there a way to do this in python?
If you use numpy you can simply make one large array that represents the two images using the numpy concatenate function:
import numpy as np
import matplotlib.pyplot as plt
img_A = np.ones((10,10))
img_B = np.ones((10,10))
plot_image = np.concatenate((img_A, img_B), axis=1)
plt.imshow(plot_image)
plt.show()

Categories

Resources