语义分割predict之后得到labels文件夹里面的坐标是归一化的坐标,先将归一化的坐标转成像素坐标(x,y),然后像素坐标结合深度图(z值)就可以得到语义分割轮廓内的点云
1、读取和转换坐标:读取归一化的坐标并转换为像素坐标,将转换后的像素坐标保存到 save_pixel 文件夹中。
2、读取深度图和save_pixel像素坐标:使用转换后的像素坐标和深度图来生成点云。
3、生成和保存点云:根据轮廓内部的像素点生成点云并保存。
import os
import numpy as np
import open3d as o3d
import cv2# 设置图像的宽度和高度
image_width = 1280 # 根据实际图像的尺寸进行设置
image_height = 720 # 根据实际图像的尺寸进行设置# 设置文件夹路径
labels_folder = r"data/predict/labels"
pixel_folder = r"data/predict/save_pixel"
depth_folder = r"data/depth"
color_folder = r"data/rgb" # 添加RGB图像的文件夹
output_folder = r"data/wuti_point"# 创建输出文件夹
os.makedirs(output_folder, exist_ok=True)# 遍历标签文件夹中的所有txt文件
for label_file in os.listdir(labels_folder):if label_file.endswith('.txt'):base_name = label_file.replace("_color.txt", "")depth_file = f"{base_name}_depth.png"pixel_file = f"{base_name}_color.txt"color_file = f"{base_name}_color.png" # RGB图像文件名# 读取标签文件并转换为像素坐标input_path = os.path.join(labels_folder, label_file)output_path = os.path.join(pixel_folder, pixel_file) # 修正了路径if not os.path.isfile(input_path):print(f"Label file not found: {input_path}")continue# 创建 pixel 文件夹,如果不存在的话os.makedirs(pixel_folder, exist_ok=True)with open(input_path, 'r') as infile, open(output_path, 'w') as outfile:lines = infile.readlines()for line in lines:values = line.split()class_id = values[0]normalized_coords = list(map(float, values[1:]))# 转换为实际像素坐标pixel_coords = []for i in range(0, len(normalized_coords), 2):x_pixel = normalized_coords[i] * image_widthy_pixel = normalized_coords[i + 1] * image_heightpixel_coords.append(f"{x_pixel:.2f}")pixel_coords.append(f"{y_pixel:.2f}")# 写入新的文件中outfile.write(f"{class_id} " + " ".join(pixel_coords) + "\n")# 读取深度图像depth_path = os.path.join(depth_folder, depth_file)if not os.path.isfile(depth_path):print(f"Depth file not found: {depth_path}")continuedepth_img = cv2.imread(depth_path, cv2.IMREAD_UNCHANGED)# 读取RGB图像color_path = os.path.join(color_folder, color_file)if not os.path.isfile(color_path):print(f"Color file not found: {color_path}")continuecolor_img = cv2.imread(color_path)# 确定对应的归一化坐标文件名pixel_path = os.path.join(pixel_folder, pixel_file)if not os.path.isfile(pixel_path):print(f"Corresponding pixel file not found for {depth_file}")continue# 读取像素坐标文件with open(pixel_path, 'r') as f:lines = f.readlines()# 提取轮廓点contour = []for line in lines:data = line.strip().split()x_coords = list(map(float, data[1::2]))y_coords = list(map(float, data[2::2]))for x, y in zip(x_coords, y_coords):contour.append([x, y])contour = np.array(contour, dtype=np.int32)# 创建一个空的点云列表points = []colors = []# 遍历图像中的每个像素for y in range(depth_img.shape[0]):for x in range(depth_img.shape[1]):# 检查该像素是否在轮廓内部或边缘if cv2.pointPolygonTest(contour, (x, y), False) >= 0:z = depth_img[y, x]if z > 0: # 忽略无效深度值points.append([x, y, z])# 获取颜色并进行归一化bgr_color = color_img[y, x] # OpenCV使用BGR格式rgb_color = bgr_color[::-1] # 转换为RGB格式colors.append(np.array(rgb_color) / 255.0) # 归一化颜色# 保存带有颜色的点云if points:point_cloud = o3d.geometry.PointCloud()point_cloud.points = o3d.utility.Vector3dVector(np.array(points))point_cloud.colors = o3d.utility.Vector3dVector(np.array(colors))output_path = os.path.join(output_folder, f"{base_name}_pointcloud.ply")o3d.io.write_point_cloud(output_path, point_cloud)print(f"Point cloud saved: {output_path}")else:print(f"No valid points found for {depth_file}")print("Point cloud generation complete.")