| import cv2 | |
| import numpy as np | |
| import matplotlib.pyplot as plt | |
| import open3d as o3d | |
| import plotly.graph_objects as go | |
| # print(pcd) | |
| # skip = 100 # Skip every n points | |
| # fig = plt.figure() | |
| # ax = fig.add_subplot(111, projection='3d') | |
| # point_range = range(0, pcd.shape[0], skip) # skip points to prevent crash | |
| # ax.scatter(pcd[point_range, 0], # x | |
| # pcd[point_range, 1], # y | |
| # pcd[point_range, 2], # z | |
| # c=pcd[point_range, 2], # height data for color | |
| # cmap='spectral', | |
| # marker="x") | |
| # ax.axis('scaled') # {equal, scaled} | |
| # plt.show() | |
| # pcd_o3d = o3d.geometry.PointCloud() # create point cloud object | |
| # pcd_o3d.points = o3d.utility.Vector3dVector(pcd) # set pcd_np as the point cloud points | |
| # # Visualize: | |
| # o3d.visualization.draw_geometries([pcd_o3d]) | |
| class PointCloudGenerator: | |
| def __init__(self): | |
| # Depth camera parameters: | |
| self.fx_depth = 5.8262448167737955e+02 | |
| self.fy_depth = 5.8269103270988637e+02 | |
| self.cx_depth = 3.1304475870804731e+02 | |
| self.cy_depth = 2.3844389626620386e+02 | |
| def conver_to_point_cloud_v1(self, depth_img): | |
| pcd = [] | |
| height, width = depth_img.shape | |
| for i in range(height): | |
| for j in range(width): | |
| z = depth_img[i][j] | |
| x = (j - self.cx_depth) * z / self.fx_depth | |
| y = (i - self.cy_depth) * z / self.fy_depth | |
| pcd.append([x, y, z]) | |
| return pcd | |
| def conver_to_point_cloud(self, depth_img): | |
| # get depth resolution: | |
| height, width = depth_img.shape | |
| length = height * width | |
| # compute indices: | |
| jj = np.tile(range(width), height) | |
| ii = np.repeat(range(height), width) | |
| # rechape depth image | |
| z = depth_img.reshape(length) | |
| # compute pcd: | |
| pcd = np.dstack([(ii - self.cx_depth) * z / self.fx_depth, | |
| (jj - self.cy_depth) * z / self.fy_depth, | |
| z]).reshape((length, 3)) | |
| return pcd | |
| def generate_point_cloud(self, depth_img, normalize=False): | |
| depth_img = np.array(depth_img) | |
| if normalize: | |
| # normalizing depth image | |
| depth_min = depth_img.min() | |
| depth_max = depth_img.max() | |
| normalized_depth = 255 * ((depth_img - depth_min) / (depth_max - depth_min)) | |
| depth_img = normalized_depth | |
| # convert depth to point cloud | |
| # point_cloud = self.conver_to_point_cloud(depth_img) | |
| # depth_image = o3d.geometry.Image(depth_img) | |
| depth_image = o3d.geometry.Image(np.ascontiguousarray(depth_img)) | |
| # # Create open3d camera intrinsic object | |
| # intrinsic_matrix = np.array([[self.fx_depth, 0, self.cx_depth], [0, self.fy_depth, self.cy_depth], [0, 0, 1]]) | |
| # camera_intrinsic = o3d.camera.PinholeCameraIntrinsic() | |
| # # camera_intrinsic.intrinsic_matrix = intrinsic_matrix | |
| # camera_intrinsic.set_intrinsics(640, 480, self.fx_depth, self.fy_depth, self.cx_depth, self.cy_depth) | |
| # camera settings | |
| # camera_intrinsic = o3d.camera.PinholeCameraIntrinsic( | |
| # depth_img.shape[0], depth_img.shape[1], 500, 500, depth_img.shape[0] / 2, depth_img.shape[1] / 2 | |
| # ) | |
| # Create open3d point cloud from depth image | |
| point_cloud = o3d.geometry.PointCloud.create_from_depth_image(depth_image, | |
| o3d.camera.PinholeCameraIntrinsic( o3d.camera.PinholeCameraIntrinsicParameters.PrimeSenseDefault)) | |
| return point_cloud | |
| # def display_pcd(pcd_data, use_matplotlib=True): | |
| # if use_matplotlib: | |
| # fig = plt.figure() | |
| # ax = fig.add_subplot(111, projection='3d') | |
| # for data, clr in pcd_data: | |
| # # points = np.array(data) | |
| # points = np.asarray(data.points) | |
| # skip = 5 | |
| # point_range = range(0, points.shape[0], skip) # skip points to prevent crash | |
| # if use_matplotlib: | |
| # ax.scatter(points[point_range, 0], points[point_range, 1], points[point_range, 2]*100, c=list(clr).append(1), marker='o') | |
| # # if not use_matplotlib: | |
| # # pcd_o3d = o3d.geometry.PointCloud() # create point cloud object | |
| # # pcd_o3d.points = o3d.utility.Vector3dVector(points) # set pcd_np as the point cloud points | |
| # # # Visualize: | |
| # # o3d.visualization.draw_geometries([pcd_o3d]) | |
| # if use_matplotlib: | |
| # ax.set_xlabel('X Label') | |
| # ax.set_ylabel('Y Label') | |
| # ax.set_zlabel('Z Label') | |
| # ax.view_init(elev=-90, azim=0, roll=-90) | |
| # # plt.show() | |
| # return fig | |
| # if not use_matplotlib: | |
| # o3d.visualization.draw_geometries([pcd_o3d]) | |
| def display_pcd(pcd_data): | |
| fig = go.Figure() | |
| for data, clr in pcd_data: | |
| points = np.asarray(data.points) | |
| skip = 1 | |
| point_range = range(0, points.shape[0], skip) | |
| fig.add_trace(go.Scatter3d( | |
| x=points[point_range, 0], | |
| y=points[point_range, 1], | |
| z=points[point_range, 2]*100, | |
| mode='markers', | |
| marker=dict( | |
| size=1, | |
| color='rgb'+str(clr), | |
| opacity=1 | |
| ) | |
| )) | |
| fig.update_layout( | |
| scene=dict( | |
| xaxis_title='X Label', | |
| yaxis_title='Y Label', | |
| zaxis_title='Z Label', | |
| camera=dict( | |
| eye=dict(x=0, y=0, z=-1), | |
| # up=dict(x=0, y=0, z=1), | |
| ) | |
| ) | |
| ) | |
| return fig | |
| if __name__ == "__main__": | |
| depth_img_path = "assets/images/depth_map_p1.png" | |
| depth_img = cv2.imread(depth_img_path, 0) | |
| depth_img = depth_img/255 | |
| point_cloud_gen = PointCloudGenerator() | |
| pcd = point_cloud_gen.generate_point_cloud(depth_img) | |
| display_pcd([pcd], use_matplotlib=True) | |