# Working with NumPy¶

Data structure of Open3D is natively compatible with NumPy buffer. The following tutorial generates a variant of sync function using NumPy and visualizes the function using Open3D.

  5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 # examples/Python/Basic/working_with_numpy.py import copy import numpy as np from open3d import * if __name__ == "__main__": # generate some neat n times 3 matrix using a variant of sync function x = np.linspace(-3, 3, 401) mesh_x, mesh_y = np.meshgrid(x,x) z = np.sinc((np.power(mesh_x,2)+np.power(mesh_y,2))) z_norm = (z-z.min())/(z.max()-z.min()) xyz = np.zeros((np.size(mesh_x),3)) xyz[:,0] = np.reshape(mesh_x,-1) xyz[:,1] = np.reshape(mesh_y,-1) xyz[:,2] = np.reshape(z_norm,-1) print('xyz') print(xyz) # Pass xyz to Open3D.PointCloud and visualize pcd = PointCloud() pcd.points = Vector3dVector(xyz) write_point_cloud("../../TestData/sync.ply", pcd) # Load saved point cloud and visualize it pcd_load = read_point_cloud("../../TestData/sync.ply") draw_geometries([pcd_load]) # convert Open3D.PointCloud to numpy array xyz_load = np.asarray(pcd_load.points) print('xyz_load') print(xyz_load) # save z_norm as an image (change [0,1] range to [0,255] range with uint8 type) img = Image((z_norm*255).astype(np.uint8)) write_image("../../TestData/sync.png", img) draw_geometries([img]) 

The first part of the script generates a $$n \times 3$$ matrix xyz. Each column has $$x, y, z$$ value of a function $$z = \frac{sin (x^2+y^2)}{(x^2+y^2)}$$. $$z_{norm}$$ is normalized map of $$z$$ for [0,1] range.

## From NumPy to open3d.PointCloud¶

 25 26 27 28  # Pass xyz to Open3D.PointCloud and visualize pcd = PointCloud() pcd.points = Vector3dVector(xyz) write_point_cloud("../../TestData/sync.ply", pcd) 

Open3D provides conversion from NumPy matrix to a vector of 3D vectors. By using Vector3dVector, NumPy matrix can be directly assigned for open3d.PointCloud.points.

In this manner, any similar data structure such as open3d.PointCloud.colors or open3d.PointCloud.normals can be assigned or modified using NumPy. The script saves the point cloud as a ply file for the next step.

## From open3d.PointCloud to NumPy¶

 30 31 32 33 34 35 36 37  # Load saved point cloud and visualize it pcd_load = read_point_cloud("../../TestData/sync.ply") draw_geometries([pcd_load]) # convert Open3D.PointCloud to numpy array xyz_load = np.asarray(pcd_load.points) print('xyz_load') print(xyz_load) 

As shown in this example, Vector3dVector is converted into a NumPy array using np.asarray.

The tutorial script prints two identical matrices

xyz
[[-3.00000000e+00 -3.00000000e+00 -3.89817183e-17]
[-2.98500000e+00 -3.00000000e+00 -4.94631078e-03]
[-2.97000000e+00 -3.00000000e+00 -9.52804798e-03]
...
[ 2.97000000e+00  3.00000000e+00 -9.52804798e-03]
[ 2.98500000e+00  3.00000000e+00 -4.94631078e-03]
[ 3.00000000e+00  3.00000000e+00 -3.89817183e-17]]
Writing PLY: [========================================] 100%
Reading PLY: [========================================] 100%
xyz_load
[[-3.00000000e+00 -3.00000000e+00 -3.89817183e-17]
[-2.98500000e+00 -3.00000000e+00 -4.94631078e-03]
[-2.97000000e+00 -3.00000000e+00 -9.52804798e-03]
...
[ 2.97000000e+00  3.00000000e+00 -9.52804798e-03]
[ 2.98500000e+00  3.00000000e+00 -4.94631078e-03]
[ 3.00000000e+00  3.00000000e+00 -3.89817183e-17]]


and visualizes the function: ## From NumPy to open3d.Image¶

2D Numpy matrix can be converted image. The following example converts z_norm into open3d.Image, visualize the image using draw_geometries, and save the image as a png format file.

 39 40 41 42  # save z_norm as an image (change [0,1] range to [0,255] range with uint8 type) img = Image((z_norm*255).astype(np.uint8)) write_image("../../TestData/sync.png", img) draw_geometries([img]) Note

The conversion supports uint8, uint16, or float32 with c_type storage (default NumPy behavior), dim=2 (width * height) or dim=3 (width * height * channel).