语义分割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_width
y_pixel = normalized_coords[i + 1] * image_height
pixel_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}")
continue
depth_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}")
continue
color_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.")