VTK: creating polygon and a hole with vtkDelaunay2D not working - python

I would like to render a Polygon with a hole in VTK. I found that the vtkDelaunay2D class should do the trick. I followed the tutorial here vtkDelaunay2D Example and it worked perfectly.
Afterwards I tried to create a different polygon with a different hole. And I don't get why it's not working and would like to know what I would have to change.
This is how it should look like.
This is how it looks like in reality.
This is the code I used:
import vtk
import random
points = vtk.vtkPoints()
ls = [
[2, 2], [-2, 2], [-2, -2], [2, -2],
[5, 5], [-5, 5], [-8, 0], [-5, -5], [5, -5], [8, 0],
[10, 10], [-10, 10], [-10, -10], [10, -10]
]
for x, y in ls:
points.InsertNextPoint(x, y, 0)
aPolyData = vtk.vtkPolyData()
aPolyData.SetPoints(points)
aCellArray = vtk.vtkCellArray()
cPolygon = vtk.vtkPolygon()
start = 0
for idd in range(start, start + 4):
cPolygon.GetPointIds().InsertNextId(idd)
aCellArray.InsertNextCell(cPolygon)
boundary = vtk.vtkPolyData()
boundary.SetPoints(aPolyData.GetPoints())
boundary.SetPolys(aCellArray)
delaunay = vtk.vtkDelaunay2D()
delaunay.SetInputData(aPolyData)
delaunay.SetSourceData(boundary)
################################## Actors etc:
meshMapper = vtk.vtkPolyDataMapper()
meshMapper.SetInputConnection(delaunay.GetOutputPort())
colors = vtk.vtkNamedColors()
meshActor = vtk.vtkActor()
meshActor.SetMapper(meshMapper)
meshActor.GetProperty().EdgeVisibilityOn()
meshActor.GetProperty().SetEdgeColor(colors.GetColor3d("Peacock"))
meshActor.GetProperty().SetInterpolationToFlat()
boundaryMapper = vtk.vtkPolyDataMapper()
boundaryMapper.SetInputData(boundary)
boundaryActor = vtk.vtkActor()
boundaryActor.SetMapper(boundaryMapper)
boundaryActor.GetProperty().SetColor(colors.GetColor3d("Raspberry"))
boundaryActor.GetProperty().SetLineWidth(3)
boundaryActor.GetProperty().EdgeVisibilityOn()
boundaryActor.GetProperty().SetEdgeColor(1, 1, 0)
boundaryActor.GetProperty().SetRepresentationToWireframe()
renderer = vtk.vtkRenderer()
renderWindow = vtk.vtkRenderWindow()
renderWindow.AddRenderer(renderer)
renderWindowInteractor = vtk.vtkRenderWindowInteractor()
renderWindowInteractor.SetRenderWindow(renderWindow)
renderer.AddActor(meshActor)
renderer.AddActor(boundaryActor)
renderer.SetBackground(colors.GetColor3d("Mint"))
renderWindow.SetSize(640, 480)
renderWindow.Render()
renderWindowInteractor.Start()
As far as I can tell it should work. Like in the example I create a set of points, define a boundary around the first 4 points (the should be hole) and then just render it.

Change
for idd in range(start, start + 4):
into
for idd in reversed(range(start, start + 4)):

Related

How to find the rotation matrix of 3 orthogonal vectors in space. My current method rotates the vectors to the wrong orientation

I am looking to find the rotation matrix for getting three (almost) orthogonal vectors to be in the same orientation of the world coordinate system.
My three (almost) orthogonal vectors can be represented like this in python:
vectors = np.array([[ 0.43187079, 0.90161148, 0.02417362],
[-0.46076794, 0.19750816, 0.86526495],
[ 0.77535832, -0.38482109, 0.50073167]])
The code I currently use can get the vectors to be parallel to the world coordinates but the orientation is incorrect. Running this code,
xrotation = np.arctan2(vectors[2, 1], vectors[2, 2])
xRot = np.array([[1, 0, 0],
[0, np.cos(xrotation), -np.sin(xrotation)],
[0, np.sin(xrotation), np.cos(xrotation)]])
vectors_x = np.zeros((3, 3))
for i in range(3):
vectors_x[i, :] = np.linalg.inv(xRot.transpose()) # vectors[i, :]
yrotation = np.arctan2(vectors_x[1, 2], vectors_x[1, 0])
yRot = np.array([[np.cos(yrotation), 0, np.sin(yrotation)],
[0, 1, 0],
[-np.sin(yrotation), 0, np.cos(yrotation)]])
vectors_y = np.zeros((3, 3))
for i in range(3):
vectors_y[i, :] = np.linalg.pinv(yRot.transpose()) # vectors_x[i, :]
zrotation = np.arctan2(vectors_y[0, 0], vectors_y[0, 1])
zRot = np.array([[np.cos(zrotation), -np.sin(zrotation), 0],
[np.sin(zrotation), np.cos(zrotation), 0],
[0, 0, 1]])
vectors_z = np.zeros((3, 3))
for i in range(3):
vectors_z[i, :] = np.linalg.pinv(zRot.transpose()) # vectors_y[i, :]
Gives the three rotated orthogonal vectors:
>vectors_z
>array([[-1.11022302e-16, 1.00000000e+00, 3.19660393e-09],
[ 1.00000000e+00, -3.70417658e-09, -2.77555756e-16],
[ 2.12261116e-09, -1.98949113e-09, -1.00000000e+00]])
What do I need to change in the code to get it in the correct orientation which would look like:
array([[ 1, 0, 0],
[ 0, 1, 0],
[ 0, 0, 1]])
I know it's possible to get this by rotating the vectors 90/180 deg in the correct order but there has gotta be a more efficient way to do this by doing something else in the code above.
Thanks for your time!!!
Figured it out. Switched to a ZYZ rotation pattern and redid the euler angle calculation method. Hope this helps someone some day.
import numpy as np
def z_rotation(zrotation):
z1Rot = np.array([[np.cos(zrotation), -np.sin(zrotation), 0],
[np.sin(zrotation), np.cos(zrotation), 0],
[0, 0, 1]])
return z1Rot
def y_rotation(yrotation):
yRot = np.array([[np.cos(yrotation), 0, np.sin(yrotation)],
[0, 1, 0],
[-np.sin(yrotation), 0, np.cos(yrotation)]])
return yRot
def forward_rotation(Rot,vectors_in):
vectors = np.zeros((3, 3))
for i in range(3):
vectors[i, :] = vectors_in[i, :] # Rot
return vectors
def reverse_rotation(Rot, vectors_in):
vectors = np.zeros((3, 3))
for i in range(3):
vectors[i, :] = np.linalg.pinv(Rot.transpose()) # vectors_in[i, :]
return vectors
org_vectors = np.array([[1,0,0],[0,1,0],[0,0,1]])
z1_angle = (-.5 + np.random.random()) * 1800
y_angle = (-.5 + np.random.random()) * 1800
z2_angle = (-.5 + np.random.random()) * 1800
z1 = z1_angle*np.pi/180
y = y_angle*np.pi/180
z2 = z2_angle*np.pi/180
z1Rot = z_rotation(z1)
z1vectors = forward_rotation(z1Rot, org_vectors)
yRot = y_rotation(y)
yvectors = forward_rotation(yRot, z1vectors)
z2Rot = z_rotation(z2)
z2vectors = forward_rotation(z2Rot, yvectors)
z2angle_calc = np.arctan2(z2vectors[2,1],z2vectors[2,0])
z2rot_2 = z_rotation(z2angle_calc)
new_y = forward_rotation(z2rot_2, z2vectors)
yangle_2 = np.arctan2(new_y[2,0],new_y[2,2])
yrot_2 = y_rotation(yangle_2)
new_z1 = forward_rotation(yrot_2, new_y)
z1angle_2 = yangle_2 = np.arctan2(new_z1[0,1],new_z1[0, 0])
z1rot_2 = z_rotation(z1angle_2)
new_org_vectors = forward_rotation(z1rot_2, new_z1)
print(new_org_vectors)

How can I make my polygon rotate without using the rotate function in the library

I have this graph that shows a polygon that is supposed to do what it is already doing but in addition to rotate the polygon all the time. I got this to work using the rotate transform ("r = mpl.transforms.Affine2D().rotate(theta)") but I am supposed to do this without any existing functions.
Here is my code:
import matplotlib.pyplot as plt
import math
xlist = [1, -1, -1]
ylist = [4, 5, 3]
xlist.append(xlist[0])
ylist.append(ylist[0])
plt.plot(xlist, ylist)
for i in range(len(xlist)-1):
print("Point",i,"= (",xlist[i],",",ylist[i],")")
i = 0
velocity_Y = 1
while (i < 16):
xlist = [ item+1 for item in xlist]
ylist = [ item+velocity_Y for item in ylist]
plt.plot(xlist, ylist)
velocity_Y = velocity_Y - 0.17
i = i+1
plt.axis([-2, 25, -2, 10])
plt.show()

Extract sub arrays based on kernel in numpy

I would like to know if there is an efficient method to get sub-arrays from a larger numpy array.
What I have is an application of np.where. I iterate 'manually' over x and y as offsets and apply where with a kernel to each rectangle extracted from the larger array with proper dimensions.
But is there a more direct approach in numpy's collection of methods?
import numpy as np
example = np.arange(20).reshape((5, 4))
# e.g. a cross kernel
a_kernel = np.asarray([[0, 1, 0], [1, 1, 1], [0, 1, 0]])
np.where(a_kernel, example[1:4, 1:4], 0)
# returns
# array([[ 0, 6, 0],
# [ 9, 10, 11],
# [ 0, 14, 0]])
def arrays_from_kernel(a, a_kernel):
width, height = a_kernel.shape
y_max, x_max = a.shape
return [np.where(a_kernel, a[y:(y + height), x:(x + width)], 0)
for y in range(y_max - height + 1)
for x in range(x_max - width + 1)]
sub_arrays = arrays_from_kernel(example, a_kernel)
This returns the arrays I need for further processing.
# [array([[0, 1, 0],
# [4, 5, 6],
# [0, 9, 0]]),
# array([[ 0, 2, 0],
# [ 5, 6, 7],
# [ 0, 10, 0]]),
# ...
# array([[ 0, 9, 0],
# [12, 13, 14],
# [ 0, 17, 0]]),
# array([[ 0, 10, 0],
# [13, 14, 15],
# [ 0, 18, 0]])]
The context: similar to 2D convolution I would like to apply a custom function on each of the subarrays (e.g. product of squared numbers).
At the moment, you're manually advancing a sliding window over the data - stride tricks to the rescue! (And no, I didn't just make that up - there's actually a submodule called stride_tricks in numpy!) Instead of manually building windows into the data, and calling np.where() on them, if you had the windows in an array, you could call np.where() just once. Stride tricks allow you to create such an array without even having to copy the data.
Let me explain. Normal slices in numpy create views into the original data instead of copies. This is done by referring to the original data, but changing the strides used to access the data (ie. how much to jump between two elements or two rows, and so on). Stride tricks allow you to modify those strides more freely than just slicing and reshaping does, so you can eg. iterate over the same data more than once, which is useful here.
Let me demonstrate:
import numpy as np
example = np.arange(20).reshape((5, 4))
a_kernel = np.array([[0, 1, 0], [1, 1, 1], [0, 1, 0]])
def sliding_window(data, win_shape, **kwargs):
assert data.ndim == len(win_shape)
shape = tuple(dn - wn + 1 for dn, wn in zip(data.shape, win_shape)) + win_shape
strides = data.strides * 2
return np.lib.stride_tricks.as_strided(data, shape=shape, strides=strides, **kwargs)
def arrays_from_kernel(a, a_kernel):
windows = sliding_window(a, a_kernel.shape)
return np.where(a_kernel, windows, 0)
sub_arrays = arrays_from_kernel(example, a_kernel)
The scipy.ndimage module offers a number of filters -- one of which might meet your needs. If none of those filters do what you want, you could use ndimage.generic_filter
to call a custom function on each subarray. ndimage.generic_filter is not as fast as the other ndimage filters, however.
For example,
import numpy as np
example = np.arange(20).reshape((5, 4))
a_kernel = np.asarray([[0, 1, 0], [1, 1, 1], [0, 1, 0]])
# def arrays_from_kernel(a, a_kernel):
# width, height = a_kernel.shape
# y_max, x_max = a.shape
# return [np.where(a_kernel, a[y:(y + height), x:(x + width)], 0)
# for y in range(y_max - height + 1)
# for x in range(x_max - width + 1)]
# sub_arrays = arrays_from_kernel(example, a_kernel)
# for arr in sub_arrays:
# print(arr)
# print('-'*80)
import scipy.ndimage as ndimage
def func(x):
# reject subarrays that extend beyond the border of the `example` array
if not np.isnan(x).any():
y = np.zeros_like(a_kernel, dtype=example.dtype)
np.put(y, np.flatnonzero(a_kernel), x)
print(y)
# Instead or returning 0, you can perform your desired computation on the subarray here.
# Note that you may not need the 2D array y; often, you only need the values in the 1D array x
return 0
result = ndimage.generic_filter(example, func, footprint=a_kernel, mode='constant', cval=np.nan)
For the particular problem of computing the product of squares for each subarray, you
could convert the product into a sum by taking advantage of the fact that A * B = exp(log(A)+log(B)). This would allow you to express the computation as a normal convolution. Now using ndimage.convolve can improve performance a lot. The amount of the improvement depends on the size of example:
import numpy as np
import scipy.ndimage as ndimage
import perfplot
a_kernel = np.asarray([[0, 1, 0], [1, 1, 1], [0, 1, 0]])
def orig(example, a_kernel=a_kernel):
def arrays_from_kernel(a, a_kernel):
width, height = a_kernel.shape
y_max, x_max = a.shape
return [
np.where(a_kernel, a[y : (y + height), x : (x + width)], 1)
for y in range(y_max - height + 1)
for x in range(x_max - width + 1)
]
return [np.prod(x) ** 2 for x in arrays_from_kernel(example, a_kernel)]
def alt(example, a_kernel=a_kernel):
logged = np.log(example)
result = ndimage.convolve(logged, a_kernel, mode="constant", cval=0)[1:-1, 1:-1]
return (np.exp(result) ** 2).ravel()
def make_example(N):
return np.random.random(size=(N, N))
def check(A, B):
return np.allclose(A, B)
perfplot.show(
setup=make_example,
kernels=[orig, alt],
n_range=[2 ** k for k in range(2, 11)],
logx=True,
logy=True,
xlabel="len(example)",
equality_check=check,
)

VTK rendering 2D mesh in python

so i'm trying to render a 2D mesh using vtk (in python). I have a list
of tuples containing all the points and also a list of tuples containing the
points of each cell. Just to experiment, I tried to create a polydata object
of a square with 4 elements and render it, but i ended up with this:
I would like it to show the lines connecting the nodes (like a wireframe)
instead of solid square..
This is the code to produce the image above:
def main2():
#Array of vectors containing the coordinates of each point
nodes = np.array([[0, 0, 0], [1, 0, 0], [2, 0, 0], [2, 1, 0], [2, 2, 0],
[1, 2, 0], [0, 2, 0], [0, 1, 0], [1, 1, 0]])
#Array of tuples containing the nodes correspondent of each element
elements = np.array([(0, 1, 8, 7), (7, 8, 5, 6), (1, 2, 3, 8), (8, 3, 4,
5)])
#Make the building blocks of polyData attributes
Mesh = vtk.vtkPolyData()
Points = vtk.vtkPoints()
Cells = vtk.vtkCellArray()
#Load the point and cell's attributes
for i in range(len(nodes)):
Points.InsertPoint(i, nodes[i])
for i in range(len(elements)):
Cells.InsertNextCell(mkVtkIdList(elements[i]))
#Assign pieces to vtkPolyData
Mesh.SetPoints(Points)
Mesh.SetPolys(Cells)
#Mapping the whole thing
MeshMapper = vtk.vtkPolyDataMapper()
if vtk.VTK_MAJOR_VERSION <= 5:
MeshMapper.SetInput(Mesh)
else:
MeshMapper.SetInputData(Mesh)
#Create an actor
MeshActor = vtk.vtkActor()
MeshActor.SetMapper(MeshMapper)
#Rendering Stuff
camera = vtk.vtkCamera()
camera.SetPosition(1,1,1)
camera.SetFocalPoint(0,0,0)
renderer = vtk.vtkRenderer()
renWin = vtk.vtkRenderWindow()
renWin.AddRenderer(renderer)
iren = vtk.vtkRenderWindowInteractor()
iren.SetRenderWindow(renWin)
renderer.AddActor(MeshActor)
renderer.SetActiveCamera(camera)
renderer.ResetCamera()
renderer.SetBackground(1,1,1)
renWin.SetSize(300,300)
#Interact with data
renWin.Render()
iren.Start()
main2()
I would also like to know if it's possible to have a gridline as the
background of the render window, instead of a black color, just like this:
Thanks in advance!
You can use MeshActor.GetProperty().SetRepresentationToWireframe() (https://www.vtk.org/doc/nightly/html/classvtkProperty.html#a2a4bdf2f46dc499ead4011024eddde5c) to render the actor as wireframe, or MeshActor.GetProperty().SetEdgeVisibility(True) to render it as solid with edges rendered as lines.
Regarding the render window background, I don't know.
Thanks to #MafiaSkafia I created what I was looking for, 2D grid for 3D purposes, maybe someone will be looking for something like this too.
# plane
planeSource = vtk.vtkPlaneSource()
planeSource.SetOrigin(-100.0, -100.0, 0.0)
# planeSource.SetNormal(0.0, 0.0, 1.0)
planeSource.SetResolution(100,100)
planeSource.SetPoint1(100.0,-100.0,0.0)
planeSource.SetPoint2(-100.0,100.0,0.0)
planeSource.Update()
plane = planeSource.GetOutput()
# Create a mapper and actor
mapperP = vtk.vtkPolyDataMapper()
mapperP.SetInputData(plane)
actorP = vtk.vtkActor()
actorP.SetMapper(mapperP)
actorP.GetProperty().SetColor(0,0,0)
actorP.GetProperty().EdgeVisibilityOn() # showing mesh
actorP.GetProperty().SetEdgeColor(1,1,1)
actorP.GetProperty().SetOpacity(0.2) # transparency
...
renderer.AddActor(actorP)

Applying the Sobel filter using scipy

I'm trying to apply the Sobel filter on an image to detect edges using scipy. I'm using Python 3.2 (64 bit) and scipy 0.9.0 on Windows 7 Ultimate (64 bit). Currently my code is as follows:
import scipy
from scipy import ndimage
im = scipy.misc.imread('bike.jpg')
processed = ndimage.sobel(im, 0)
scipy.misc.imsave('sobel.jpg', processed)
I don't know what I'm doing wrong, but the processed image does not look anything like what it should. The image, 'bike.jpg' is a greyscale (mode 'L' not 'RGB') image so each pixel has only one value associated with it.
Unfortunately I can't post the images here yet (don't have enough reputation) but I've provided links below:
Original Image (bike.jpg):
http://s2.postimage.org/64q8w613j/bike.jpg
Scipy Filtered (sobel.jpg):
http://s2.postimage.org/64qajpdlb/sobel.jpg
Expected Output:
http://s1.postimage.org/5vexz7kdr/normal_sobel.jpg
I'm obviously going wrong somewhere! Can someone please tell me where. Thanks.
1) Use a higher precision. 2) You are only calculating the approximation of the derivative along the zero axis. The 2D Sobel operator is explained on Wikipedia. Try this code:
import numpy
import scipy
from scipy import ndimage
im = scipy.misc.imread('bike.jpg')
im = im.astype('int32')
dx = ndimage.sobel(im, 0) # horizontal derivative
dy = ndimage.sobel(im, 1) # vertical derivative
mag = numpy.hypot(dx, dy) # magnitude
mag *= 255.0 / numpy.max(mag) # normalize (Q&D)
scipy.misc.imsave('sobel.jpg', mag)
I couldn't comment on cgohlke's answer so I repeated his answer with a corrction. Parameter 0 is used for vertical derivative and 1 for horizontal derivative (first axis of an image array is y/vertical direction - rows, and second axis is x/horizontal direction - columns). Just wanted to warn other users, because I lost 1 hour searching for mistake in the wrong places.
import numpy
import scipy
from scipy import ndimage
im = scipy.misc.imread('bike.jpg')
im = im.astype('int32')
dx = ndimage.sobel(im, 1) # horizontal derivative
dy = ndimage.sobel(im, 0) # vertical derivative
mag = numpy.hypot(dx, dy) # magnitude
mag *= 255.0 / numpy.max(mag) # normalize (Q&D)
scipy.misc.imsave('sobel.jpg', mag)
or you can use :
def sobel_filter(im, k_size):
im = im.astype(np.float)
width, height, c = im.shape
if c > 1:
img = 0.2126 * im[:,:,0] + 0.7152 * im[:,:,1] + 0.0722 * im[:,:,2]
else:
img = im
assert(k_size == 3 or k_size == 5);
if k_size == 3:
kh = np.array([[-1, 0, 1], [-2, 0, 2], [-1, 0, 1]], dtype = np.float)
kv = np.array([[1, 2, 1], [0, 0, 0], [-1, -2, -1]], dtype = np.float)
else:
kh = np.array([[-1, -2, 0, 2, 1],
[-4, -8, 0, 8, 4],
[-6, -12, 0, 12, 6],
[-4, -8, 0, 8, 4],
[-1, -2, 0, 2, 1]], dtype = np.float)
kv = np.array([[1, 4, 6, 4, 1],
[2, 8, 12, 8, 2],
[0, 0, 0, 0, 0],
[-2, -8, -12, -8, -2],
[-1, -4, -6, -4, -1]], dtype = np.float)
gx = signal.convolve2d(img, kh, mode='same', boundary = 'symm', fillvalue=0)
gy = signal.convolve2d(img, kv, mode='same', boundary = 'symm', fillvalue=0)
g = np.sqrt(gx * gx + gy * gy)
g *= 255.0 / np.max(g)
#plt.figure()
#plt.imshow(g, cmap=plt.cm.gray)
return g
for more see here

Categories

Resources