深度相機同時拍攝xyz點云文件和jpg圖像文件。xyz文件里面包含三維坐標[x,y,z]和jpg圖像文件包含二維坐標[x,y],但是不能直接進行變換,需要一定的步驟來推演。
下面函數是通過box二維框[xmin, ymin, xmax, ymax, _, _ ]去截取xyz文件中對應box里面的點云,返回點云的numpy數組
def get_point_from_xyz_and_box(self, Image_XYZ_Name, box, p=0.1, Sampling_interval=4):#改進的讀取點云的函數,可以節省很多時間# 使用內存映射讀取文件with open(Image_XYZ_Name, "rb") as fd:# 計算映射大小和偏移dtype = np.dtype(np.uint16)offset = dtype.itemsize * self.width * self.height * 3 #根據文件格式調整fd.seek(0, 2) # 移動到文件末尾file_size = fd.tell()assert file_size >= offset, "文件大小不匹配"# 創建內存映射mm = np.memmap(fd, dtype=dtype, mode='r', shape=(self.height, self.width, 3), order="C")# 轉換為3D點云,只讀取box范圍內的xmin, ymin, xmax, ymax, _, _ = boxy_indices = np.arange(ymin, ymax, Sampling_interval, dtype=int)x_indices = np.arange(xmin, xmax, Sampling_interval, dtype=int)# 構建網格索引y_grid, x_grid = np.meshgrid(y_indices, x_indices, indexing='ij')depth_points = mm[y_grid, x_grid].reshape(-1, 3) * p# print('mm',mm) # print(y_grid, x_grid) # 過濾無效點(假設深度值為0表示無效點)valid_points = depth_points[depth_points[:, 2] != 0]return valid_points
下面函數是知道點云中的一個點[x,y,z]來計算出這個點對應的二維坐標[y,x]
def calculate_box_from_points_and_xyz(self, point, p=0.1):with open(self.XYZ_Name, "rb") as fd:# 計算映射大小和偏移dtype = np.dtype(np.uint16)offset = dtype.itemsize * self.width * self.height * 3 # 根據文件格式調整fd.seek(0, 2) # 移動到文件末尾file_size = fd.tell()assert file_size >= offset, "文件大小不匹配"# 創建內存映射a = np.memmap(fd, dtype=dtype, mode='r', shape=(self.height, self.width, 3), order="C")# 將所有點的坐標轉換為KD樹需要的格式,并除以ppoints = np.reshape(a, (-1, 3)) kd_tree = KDTree(points)# 查找最接近的點point_idx = kd_tree.query(point / p)[1]# 將一維索引轉換回二維索引matching_indice = np.unravel_index(point_idx, (self.height, self.width))return matching_indice