How to add texture to a mesh in python Open3d?

Viewed 6949

I am working with a triangle meshes with python Open3d and I want to add a texture mapping to my mesh (I didn't find it in the documentation), this is an example code with simple cube mesh:

import numpy as np
import open3d as o3d

vert=[[0,0,0],[0,1,0],[1,1,0],[1,0,0],
   [0,0,1],[0,1,1],[1,1,1],[1,0,1]]

faces=[[0, 1, 2], [0, 2, 3], [6, 5, 4],
 [7, 6, 4], [5, 1, 0], [0, 4, 5], [3, 2, 6],
 [6, 7, 3], [0, 3, 7], [0, 7, 4], [1, 5, 6],
 [1, 6, 2]]

m=o3d.geometry.TriangleMesh(o3d.open3d_pybind.utility.Vector3dVector(vert),
                            o3d.open3d_pybind.utility.Vector3iVector(faces))

m.compute_vertex_normals()
o3d.visualization.draw_geometries([m])

I can see the cube: cube mesh

Now I try to add texture:

text=cv2.imread('~/Downloads/cupe_uv.png')
plt.imshow(text)

this is the texture image: texture image of a cube

DX,DY=0.5/2,0.66/2
v_uv=[[DX,DY],[DX,2*DY],[2*DX,2*DY],[2*DX,DY],
      [0,DX],[DX,1],[3*DX,2*DY],[3*DX,DY]]

v_uv=np.asarray(v_uv)
v_uv=np.concatenate((v_uv,v_uv,v_uv),axis=0)
m.triangle_uvs = o3d.open3d_pybind.utility.Vector2dVector(v_uv)

m.textures=[o3d.geometry.Image(text)]

o3d.visualization.draw_geometries([m])

I know I didn't set the uv coordinates to display all the colors of the cube (but some colors should be there...). Any way the mesh is still with out texture (same as in the beginning).

2 Answers

mesh.triangle_uvs is an array of shape (3 * num_triangles, 2), not (3 * num_vertices, 2).

Try this:

v_uv = np.random.rand(len(faces) * 3, 2)
m.triangle_uvs = o3d.open3d_pybind.utility.Vector2dVector(v_uv)

By the way, it seems that your Open3D version is quite old.
Open3d 0.10.0 is already out and a lot of new features added.
You might wanna try the new version :)

like Jing Zhao said in https://stackoverflow.com/a/63005705/15099601

v_uv = np.random.rand(len(faces) * 3, 2) m.triangle_uvs =
o3d.open3d_pybind.utility.Vector2dVector(v_uv)

will work. For Open3d Versions 0.10.0 the material_ids do not seem to get set.

m.triangle_material_ids = o3d.utility.IntVector([0]*len(faces))

fixes that, so that the textured cube can be visualized without crashing

Related