Closed sw-gong closed 5 years ago
possible solution with vedo:
import trimesh
from vedo import Points, show
mesh = trimesh.creation.icosphere()
mesh.visual.face_colors = [200, 200, 250, 100]
n = mesh.vertices.shape[0]
#Assign a color based on a scalar and a color map
pc1 = Points(mesh.vertices, r=10)
pc1.cmap("jet", list(range(n)))
pc2 = Points(mesh.vertices, r=10)
pc2.cmap("viridis", mesh.vertices[:,2])
# Draw result on N=2 sync'd renderers
show([(mesh,pc1), (mesh,pc2)], N=2, axes=1)
possible solution with vtkplotter:
import trimesh mesh = trimesh.creation.icosphere() mesh.visual.face_colors = [200, 200, 250, 100] from vtkplotter import * n = mesh.vertices.shape[0] pc1 = Points(mesh.vertices, r=10) #Assign a color to each vertex individually, # format can be integer, tuple, string name: # (method name will change in future release) pc1.colorVerticesByArray(range(n)) #Assign a color based on a scalar and a color map pc2 = Points(mesh.vertices, r=10) pc2.pointColors(mesh.vertices[:,2], cmap='viridis') # Draw result on N=2 sync'd renderers, white background show([(mesh,pc1), (mesh,pc2)], N=2, bg="white", axes=1)
I have tried your code and it shows the below error:
Do you know the reason?
Do you know how to draw 3d shapes like this? It includes drawing meshes in a row with a white background and color each vertex with some consistent values
You could also use a trimesh.Scene
object (or check out the widget
example for something more advanced):
mikedh@cue:~$ ipython -i
Python 3.6.9 |Anaconda, Inc.| (default, Jul 30 2019, 19:07:31)
Type 'copyright', 'credits' or 'license' for more information
IPython 6.5.0 -- An enhanced Interactive Python. Type '?' for help.
In [1]: import trimesh
In [2]: meshes = [trimesh.creation.uv_sphere() for i in range(10)]
In [3]: for i, m in enumerate(meshes):
...: m.apply_translation([0,0, i*2])
...: m.visual.vertex_colors = trimesh.visual.random_color()
...:
In [6]: trimesh.Scene(meshes).show()
You could also use a
trimesh.Scene
object (or check out thewidget
example for something more advanced):mikedh@cue:~$ ipython -i Python 3.6.9 |Anaconda, Inc.| (default, Jul 30 2019, 19:07:31) Type 'copyright', 'credits' or 'license' for more information IPython 6.5.0 -- An enhanced Interactive Python. Type '?' for help. In [1]: import trimesh In [2]: meshes = [trimesh.creation.uv_sphere() for i in range(10)] In [3]: for i, m in enumerate(meshes): ...: m.apply_translation([0,0, i*2]) ...: m.visual.vertex_colors = trimesh.visual.random_color() ...: In [6]: trimesh.Scene(meshes).show()
Awesome! One more question, If I know each vertex is related to some value, I want to color vertices based on these values (ideally, values from low to high are related to a color map, just like the image I attached in the last reply). Do you know how to draw like this way?
Hey, yeah you could use trimesh.visual.interpolate
for that:
In [1]: import trimesh
In [2]: import numpy as np
In [3]: meshes = [trimesh.creation.uv_sphere() for i in range(10)]
In [4]: trimesh.visual.interpolate?
Signature: trimesh.visual.interpolate(values, color_map=None, dtype=<class 'numpy.uint8'>)
Docstring:
Given a 1D list of values, return interpolated colors
for the range.
Parameters
---------------
values : (n, ) float
Values to be interpolated over
color_map : None, or str
Key to a colormap contained in:
matplotlib.pyplot.colormaps()
e.g: 'viridis'
Returns
-------------
interpolated : (n, 4) dtype
Interpolated RGBA colors
File: ~/trimesh/trimesh/visual/color.py
Type: function
In [5]: for i, m in enumerate(meshes):
...: m.vertices *= (np.random.random(3) + 1 ) * 2
...: m.apply_translation([0,0, i*6])
...:
...: radii = np.linalg.norm(m.vertices - m.center_mass, axis=1)
...: m.visual.vertex_colors = trimesh.visual.interpolate(radii, color_map='viridis')
...:
In [6]: trimesh.Scene(meshes).show()
I have tried your code and it shows the below error:
Do you know the reason?
Oh, that's because jupyter notebook rendering does not support more than one rendering window (I will add a more meaningful error message)..
You need to add embedWindow(False)
in that case. Otherwise try:
(this should also work in jupyter)
import trimesh
from vedo import trimesh2vedo, show
meshes = [trimesh.creation.uv_sphere().apply_translation([0,0,i*2]) for i in range(3)]
vmeshes = trimesh2vedo(meshes)
for i in range(3):
scals = vmeshes[i].points()[:,i] # define some dummy point scalar
vmeshes[i].cmap("jet", scals)
show(vmeshes, axes=1)
Hey, yeah you could use
trimesh.visual.interpolate
for that:In [1]: import trimesh In [2]: import numpy as np In [3]: meshes = [trimesh.creation.uv_sphere() for i in range(10)] In [4]: trimesh.visual.interpolate? Signature: trimesh.visual.interpolate(values, color_map=None, dtype=<class 'numpy.uint8'>) Docstring: Given a 1D list of values, return interpolated colors for the range. Parameters --------------- values : (n, ) float Values to be interpolated over color_map : None, or str Key to a colormap contained in: matplotlib.pyplot.colormaps() e.g: 'viridis' Returns ------------- interpolated : (n, 4) dtype Interpolated RGBA colors File: ~/trimesh/trimesh/visual/color.py Type: function In [5]: for i, m in enumerate(meshes): ...: m.vertices *= (np.random.random(3) + 1 ) * 2 ...: m.apply_translation([0,0, i*6]) ...: ...: radii = np.linalg.norm(m.vertices - m.center_mass, axis=1) ...: m.visual.vertex_colors = trimesh.visual.interpolate(radii, color_map='viridis') ...: In [6]: trimesh.Scene(meshes).show()
Hi,
After trying it, I still have a few questions:
trimesh.scene
(multiple meshes) to .ply
or other files or save a screen shot of it to png
?m.apply_translation([0,0, i*6])
, but for other meshes, this may not be true)? Or is there any convenient way to set it? For example, is it possible to initialize a window with the size of [2, 4]
(8 boxes), and each mesh is placed on a single box assuming 8 meshes in total in this case. Therefore, we don't need to mannually translate each mesh.Hey, first of all thank you for this awesome library!!! I am also very interested in a visualiziation of the colorbar.
Hi, here is a function to plot a separate figure with the colormap before showing the pyglet figure. It would clearly be better to plot the colorbar within the same figure, but I don't know how to do that.
Hope it helps
import trimesh import numpy as np import matplotlib.pyplot as plt
def pyglet_plot(mesh, values=None, color_map=None, plot_colormap=False, caption=None): """ Visualize a trimesh object using pyglet as proposed in trimesh the added value is for texture visualization :param mesh: trimesh object :param values: numpy array of a texture to be visualized on the mesh :param color_map: str, matplotlib colormap, default is 'jet' :param plot_colormap: Boolean, if True use matplotlib to plot the colorbar of the map on a separate figure :param caption: Title of window :return: """
if values is not None:
smooth = True
if color_map is None:
color_map = 'jet'
vect_col_map = \
trimesh.visual.color.interpolate(values, color_map=color_map)
if values.shape[0] == mesh.vertices.shape[0]:
mesh.visual.vertex_colors = vect_col_map
elif values.shape[0] == mesh.faces.shape[0]:
mesh.visual.face_colors = vect_col_map
smooth = False
if plot_colormap:
gradient = np.linspace(0, 1, 256)
gradient = np.vstack((gradient, gradient))
fig, ax = plt.subplots(1, 1)
# fig.subplots_adjust(top=0.95, bottom=0.05, left=0.01, right=0.99)
ax.set_title(caption)
ax.imshow(gradient, aspect='auto', cmap=plt.get_cmap(color_map))
pos = list(ax.get_position().bounds)
y_text = pos[1] + pos[3] / 2.
fig.text(pos[0] - 0.01, y_text,
'{:0.0000009f}'.format(np.min(values)),
va='center', ha='right', fontsize=15, color='k')
fig.text(pos[2] + pos[0] + 0.01, y_text,
'{:0.0000009f}'.format(np.max(values)),
va='center', fontsize=15, color='k')
ax.set_axis_off()
plt.show()
# call the default trimesh visualization tool using pyglet
mesh.show(caption=caption, smooth=smooth)
Hey Gauzias, Thank you! I also noticed the tutorials for the vtkplotter library e.g. : https://github.com/marcomusy/vtkplotter/blob/master/examples/advanced/moving_least_squares3D.py that helped a lot! Greetings, Julian
Hey Gauzias, Thank you! I also noticed the tutorials for the vtkplotter library e.g. : https://github.com/marcomusy/vtkplotter/blob/master/examples/advanced/moving_least_squares3D.py that helped a lot! Greetings, Julian
you can add a 2D scalarbar with e.g.:
import trimesh
meshes = [trimesh.creation.uv_sphere().apply_translation([0,0,i*2]) for i in range(3)]
from vtkplotter import trimesh2vtk, show
vtkmeshes = [trimesh2vtk(m) for m in meshes]
for i in range(3):
scals = vtkmeshes[i].coordinates()[:,i] # define some dummy point scalar
vtkmeshes[i].pointColors(scals, cmap='jet')
vtkmeshes[0].addScalarBar(title="my scalarbar")
show(vtkmeshes, bg='w', axes=1)
Hey Gauzias, Thank you! I also noticed the tutorials for the vtkplotter library e.g. : https://github.com/marcomusy/vtkplotter/blob/master/examples/advanced/moving_least_squares3D.py that helped a lot! Greetings, Julian
you can add a 2D scalarbar with e.g.:
import trimesh meshes = [trimesh.creation.uv_sphere().apply_translation([0,0,i*2]) for i in range(3)] from vtkplotter import trimesh2vtk, show vtkmeshes = [trimesh2vtk(m) for m in meshes] for i in range(3): scals = vtkmeshes[i].coordinates()[:,i] # define some dummy point scalar vtkmeshes[i].pointColors(scals, cmap='jet') vtkmeshes[0].addScalarBar(title="my scalarbar") show(vtkmeshes, bg='w', axes=1)
Hi @marcomusy ,
I installed vtkplotter with pip install vtkplotter
, but it shows the error ImportError: cannot import name 'trimesh2vtk'
. Do you know why it is? Additionally, can you plot things without the background (only white) if using your library?
sorry, can you try:
from vtkplotter import show
from vtkplotter.trimesh import trimesh2vtk
# to eliminate axes
show(vtkmeshes, bg='white', axes=0)
Hey Gauzias, Thank you! I also noticed the tutorials for the vtkplotter library e.g. : https://github.com/marcomusy/vtkplotter/blob/master/examples/advanced/moving_least_squares3D.py that helped a lot! Greetings, Julian
you can add a 2D scalarbar with e.g.:
import trimesh meshes = [trimesh.creation.uv_sphere().apply_translation([0,0,i*2]) for i in range(3)] from vtkplotter import trimesh2vtk, show vtkmeshes = [trimesh2vtk(m) for m in meshes] for i in range(3): scals = vtkmeshes[i].coordinates()[:,i] # define some dummy point scalar vtkmeshes[i].pointColors(scals, cmap='jet') vtkmeshes[0].addScalarBar(title="my scalarbar") show(vtkmeshes, bg='w', axes=1)
Hi @marcomusy ,
I installed vtkplotter with
pip install vtkplotter
, but it shows the errorImportError: cannot import name 'trimesh2vtk'
. Do you know why it is? Additionally, can you plot things without the background (only white) if using your library?
Had the same problem. You have to clone the current release here from github. in the version of pip these file are missing yet. And it is possible to set a white background. See the following tutorial:
https://github.com/marcomusy/vtkplotter/blob/master/examples/advanced/fitspheres1.py
sorry, can you try:
from vtkplotter import show from vtkplotter.trimesh import trimesh2vtk # to eliminate axes show(vtkmeshes, bg='white', axes=0)
Thanks!
It works and looks really nice!
Does the viewer support actions like the viewer used in trimesh like below?
How to export this mesh or this view?
Addtionally, when view from jupyter notebook, I set embedWindow(False)
, the kernel died every time.
@sw-gong
Does the viewer support actions like the viewer used in trimesh like below?
Yes, press h
in window and it will show (in terminal) a helper message with all different options
How to export this mesh or this view?
Press S
to a png screenshot or E
to export all meshes to a single numpy file (this is still experimental, different color mappings are not yet supported). Or can save individual meshes in various formats with e.g. actor.write('mesh.ply')
Addtionally, when view from jupyter notebook, I set embedWindow(False), the kernel died every time.
Thanks I will investigate the issue..
Hi @marcomusy,
Is that possible to export mesh (.ply or other file types which can be loaded by meshlab directly) with colored vertices via vtkplotter
?
Hey, if the colors are set in mesh.visual.vertex_colors
they should export when you save it as ply
. If they are set, mesh.visual.kind == 'vertex'
should be true.
@sw-gong sorry for the late reply,
yes - you should be able to do it with the latest version:
pip install --upgrade vedo
then
from trimesh.creation import uv_sphere
meshes = [uv_sphere().apply_translation([0,i*2.1,0]) for i in range(3)]
###############################################
from vedo import trimesh2vedo, show
vmeshes = trimesh2vedo(meshes)
cmaps = ('jet', 'PuOr', 'viridis')
for i in range(3):
scals = vmeshes[i].points()[:,i] # define some dummy point scalar
vmeshes[i].cmap(cmaps[i], scals).lighting('plastic')
# add a 2D scalar bar to a mesh
vmeshes[0].addScalarBar(title="my scalarbar\nnumber #0", c='k')
# add 3D scalar bars
vmeshes[1].addScalarBar3D(pos=(1.2,2.1,-1.0), c='k')
show(vmeshes, axes=1)
note that
ply
files with color info. (see example), but some some reason that doesnt work for the above example, so better follow the suggestion from mikedh.Thanks for reporting and for your feedback, Best
Thanks! @marcomusy @mikedh
Hey guys! Your images are so great! Is it possible to show them screenless (as folder/xxx.png) when using a remote server without x11 or screen? (instead of a pop-up window every time)
@ZENGYIMING-EAMON yes check out https://github.com/marcomusy/vedo/issues/64
how can i calculate the error? np.linalg.norm(mesh.vertices-label.vertices,axis=1)?
@sw-gong Do you have the script to create the face heatmap? I am working on a 3d face reconstruction project, so I am wonder how I can have my error distances results calculated and displayed as a heatmap.
from vtkplotter import show from vtkplotter.trimesh import trimesh2vtk # to eliminate axes show(vtkmeshes, bg='white', axes=0)
@sw-gong Do you have the script to create the face heatmap? I am working on a 3d face reconstruction project, so I am wonder how I can have my error distances results calculated and displayed as a heatmap.
I have the same issue. Could find a way to visualize the distance results?
I have the same issue. Could find a way to visualize the distance results?
Try:
import numpy as np
from trimesh.creation import uv_sphere
from vedo import Mesh, show
tmsh = uv_sphere() # trimesh object
vmsh = Mesh(tmsh) # vedo object
# Add a scalar field to the mesh
scalar_field = np.random.randn(vmsh.npoints)
vmsh.cmap("viridis", scalar_field)
vmsh.add_scalarbar3d(title="residuals")
show(vmsh, axes=1)
Hi,
Thanks for the good library.
May I ask how to color vertices on meshes and how to visualize several meshes in a row with a specific background?