Render segmentation, stored in a NumPy array, with VTK - vtk

I have a segmentation, in a 3D numpy.ndarray, which I would like to render into VTK. [See here similar process here: https://pyscience.wordpress.com/2014/11/16/volume-rendering-with-python-and-vtk/ by#somada141]
My current (ad-hoc) solution includes:
(1) Save the NumPy array to a Nifiti file with nib. Nifti1Image
(2) Load the Nifiti file into vtk with (vtkNIFTIImageReader())
(3) Render the surface with vtkDiscreteMarchingCubes()
My question: How can I convert this 3D NumPy array directly into VTK without the intermediate file.

You can use the module numpy_support( https://github.com/Kitware/VTK/blob/master/Wrapping/Python/vtk/util/numpy_support.py) or the new vtk datasetadapter http://www.paraview.org/ParaView3/Doc/Nightly/www/py-doc/paraview.vtk.numpy_interface.dataset_adapter.html , http://kitware.com/blog/home/post/709
For an example of the first solution see https://pyscience.wordpress.com/2014/09/06/numpy-to-vtk-converting-your-numpy-arrays-to-vtk-arrays-and-files/
Actually while I was looking for an example I found also http://www.vtk.org/Wiki/VTK/Examples/Python/vtkWithNumpy, which I never tried before!

Related

How to view sparse matrix as np array when loading from npy files?

I have some npy files and I want to load them as normal arrays to see their contents, usually, when I use np.load() it would give me nd-arrays directly, but for this file, I have to set allow_pickle=True to get the loading work first, then when I print it, I get lines (in the image below) instead of arrays. I tried the d[()] but it gives the exact same output as print(d).
Is there any way I could load them as normal nd-arrays? I'm using Python 3 on Jupiter notebook.

pytorch make_grid (from torchvision.utils import make_grid) behaves different then I expect

trying to run the visualization utils tutorial from pytorch, I tried it with some images of dogs found on the internet. the images used in the tutorial are not distributed for use.. making the gris and showing the result behaves funny - it shows each channel as a separate image (I guess this is what I see)
so - from the tutorial
but here is what I get from the images I got:
I was expecting to see the two images in their original colors in a grid.
Another step I tried following Ivan's comment:
tutorial: https://pytorch.org/vision/master/auto_examples/plot_visualization_utils.html
I would like to know how to fix this (and use make_grid correctly)
For the output you got, I would assume the correct shape is (height, width, channels) instead of (channels, height, width). You can correct this with torch.permute. The following should provide the desired result:
>>> grid = make_grid(torch.stack([transformed_dog1, transformed_dog2]).permute(0,3,1,2))
>>> show(grid)

Using paraview filters in Python, Paraview python api

I have been using Paraview to visualize and analyse VTU files. I find the calculate gradient filter quite useful. I would like to know if there is a python API for Paraview which I can use to use this filter.
I'm looking for something like this.
import paraview as pv
MyFile = "Myfile0001.vtu"
Divergence = pv.filters.GradientOfUnstructuredDataset.(Myfile)
ParaView is fully scriptable in python. Each part of this doc has a 'do it in python' version.
Whereas API doc does not necessary exist, you can use the Python Trace (in Tool menu), that records action from the GUI and save it as a python script.
EDIT
To get back data as an array, it needs some additional steps as ParaView works on a client/server mode. You should Fetch the data and then you can manipulate the vtkObject, extract the array and convert it to numpy.
Something like
from paraview.simple import *
from vtk.numpy_interface import dataset_adapter as dsa
gridvtu = XMLUnstructuredGridReader(registrationName='grid', FileName=['grid.vtu'])
gradient = GradientOfUnstructuredDataSet(registrationName='Gradient', Input=gridvtu)
vtk_grid = servermanager.Fetch(gradient)
wraped_grid = dsa.WrapObject(vtk_grid)
divergence_array = wraped_grid.PointData["Divergence"]
Note that divergence_array is a numpy.ndarray
You also can write pure vtk code, as in this example on SO

Problems Converting Numpy/OpenCV Array Image into a Wand Image

I'm currently trying to perform a Polar to Cartesian Coordinate Image transformation, to display a raw sonar image into a 'fan-display'.
Initially I have a Numpy Array image of type np.float64, that can be seen below:
After doing some searching, I came across this StackOverflow post Inverse transform an image from Polar to Cartesian in OpenCV with a very similar problem, in which the poster seemed to have solved his/her issue by using the Python Wand library (http://docs.wand-py.org/en/0.5.9/index.html), specifically using their set of Distortion functions.
However, when I tried to use Wand and read the image in, I instead ended up with Wand getting the image below, which seems to be smaller than the original one. However, the weird thing is that img.size still gives the same size number as the original image's shape.
The code for this transformation can be seen below:
print(raw_img.shape)
wand_img = Image.from_array(raw_img.astype(np.uint8), channel_map="I") #=> (369, 256)
display(wand_img)
print("Current image size", wand_img.size) #=> "Current image size (369, 256)"
This is definitely quite problematic as Wand will automatically give the wrong 'fan image'. Is anybody familiar with this kind of problem with the Wand library previously, and if yes, may I ask what is the recommended solution to fix this issue?
If this issue isn't resolved soon I have an alternative backup of using OpenCV's cv::remap function (https://docs.opencv.org/4.1.2/da/d54/group__imgproc__transform.html#ga5bb5a1fea74ea38e1a5445ca803ff121). However the problem with this is that I'm not sure what mapping arrays (i.e. map_x and map_y) to use to perform the Polar->Cartesian transformation, as using a mapping matrix that implements the transformation equations below:
r = polar_distances(raw_img)
x = r * cos(theta)
y = r * sin(theta)
didn't seem to work and instead threw out errors from OpenCV as well.
Any kind of help and insight into this issue is greatly appreciated. Thank you!
- NickS
EDIT I've tried on another image example as well, and it still shows a similar problem. So first, I imported the image into Python using OpenCV, using these lines of code:
import matplotlib.pyplot as plt
from wand.image import Image
from wand.display import display
import cv2
img = cv2.imread("Test_Img.jpg")
img_rgb = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
plt.figure()
plt.imshow(img_rgb)
plt.show()
which showed the following display as a result:
However, as I continued and tried to open the img_rgb object with Wand, using the code below:
wand_img = Image.from_array(img_rgb)
display(img_rgb)
I'm getting the following result instead.
I tried to open the image using wand.image.Image() on the file directly, which is able to display the image correctly when using display() function, so I believe that there isn't anything wrong with the wand library installation on the system.
Is there a missing step that I required to convert the numpy into Wand Image that I'm missing? If so, what would it be and what is the suggested method to do so?
Please do keep in mind that I'm stressing the conversion of Numpy to Wand Image quite crucial, the raw sonar images are stored as binary data, thus the required use of Numpy to convert them to proper images.
Is there a missing step that I required to convert the numpy into Wand Image that I'm missing?
No, but there is a bug in Wand's Numpy implementation in Wand 0.5.x. The shape of OpenCV's ndarray is (ROWS, COLUMNS, CHANNELS), but Wand's ndarray is (WIDTH, HEIGHT, CHANNELS). I believe this has been fixed for the future 0.6.x releases.
If so, what would it be and what is the suggested method to do so?
Swap the values in img_rgb.shape before passing to Wand.
img_rgb.shape = (img_rgb.shape[1], img_rgb.shape[0], img_rgb.shape[2],)
with Image.from_array(img_rgb) as img:
display(img)

How to overlay images on each other in python and opencv?

I am trying to write images over each other. Ideally, what I want to do is to write every image in one folder over every image in another folder and output every unique image to another folder. So far, I am just working on having one image write over one image, but I can't seem to get that to work.
import numpy as np
import cv2
import matplotlib
def opencv_createsamples():
mask = ('resized_pos/2')
img = cv2.imread('neg/1')
new_img = img * (mask.astype(img.dtype))
cv2.imwrite('samp', new_img)
opencv_createsamples()
It would be helpful to have more information about your errors.
Something that stands out immediately is the lack of file type extensions. Your images are probably not being read correctly, to begin with. Also, image sizes would be a good thing to consider so you could resize as required.
If the goal is to blend images, considering the alpha channel is important. Here is a relevant question on StackOverflow:How to overlay images in python
Some other OpenCV docs that have helped me in the past: https://docs.opencv.org/trunk/d0/d86/tutorial_py_image_arithmetics.html
https://docs.opencv.org/3.1.0/d5/dc4/tutorial_adding_images.html
Hope this helps!

Resources