Solaria1.0 / pointcloud.py
CronosSa's picture
Update pointcloud.py
6f4e9ea verified
Raw History Blame
3.19 kB
import numpy as np
def depth_to_pointcloud(depth, image=None, stride=4):
"""
Converte um mapa de profundidade em uma nuvem de pontos 3D.
depth:
Array 2D com os valores de profundidade.
image:
Imagem RGB original para colorir os pontos.
stride:
Intervalo entre pixels.
stride=4 significa que usamos 1 a cada 4 pixels.
"""
depth = np.asarray(depth, dtype=np.float32)
if depth.ndim != 2:
raise ValueError(
f"Depth precisa ser 2D. Formato recebido: {depth.shape}"
)
height, width = depth.shape
# Seleciona os pixels
y, x = np.mgrid[
0:height:stride,
0:width:stride
]
z = depth[::stride, ::stride]
# Remove valores inválidos
valid = np.isfinite(z)
x = x[valid].astype(np.float32)
y = y[valid].astype(np.float32)
z = z[valid].astype(np.float32)
if len(z) == 0:
raise ValueError(
"Não foram encontrados valores válidos de profundidade."
)
# Normaliza Z entre 0 e 1
z_min = np.min(z)
z_max = np.max(z)
if z_max - z_min > 1e-8:
z = (z - z_min) / (z_max - z_min)
else:
z[:] = 0.5
# Centraliza X e Y
x = (x - width / 2) / width
y = -(y - height / 2) / height
# Aumenta a profundidade para facilitar a visualização
z = z * 2.0
points = np.stack(
[x, y, z],
axis=1
)
colors = None
if image is not None:
image = image.convert("RGB")
image_array = np.asarray(
image.resize((width, height))
)
sampled_colors = image_array[
::stride,
::stride
]
colors = sampled_colors[valid]
return points, colors
def save_pointcloud_ply(filename, points, colors=None):
"""
Salva uma nuvem de pontos no formato PLY.
"""
points = np.asarray(points)
if points.ndim != 2 or points.shape[1] != 3:
raise ValueError(
"points precisa ter formato (N, 3)."
)
with open(filename, "w", encoding="utf-8") as file:
file.write("ply\n")
file.write("format ascii 1.0\n")
file.write(f"element vertex {len(points)}\n")
file.write("property float x\n")
file.write("property float y\n")
file.write("property float z\n")
if colors is not None:
file.write("property uchar red\n")
file.write("property uchar green\n")
file.write("property uchar blue\n")
file.write("end_header\n")
if colors is not None:
for point, color in zip(points, colors):
x, y, z = point
r, g, b = color
file.write(
f"{x:.6f} "
f"{y:.6f} "
f"{z:.6f} "
f"{int(r)} "
f"{int(g)} "
f"{int(b)}\n"
)
else:
for point in points:
x, y, z = point
file.write(
f"{x:.6f} "
f"{y:.6f} "
f"{z:.6f}\n"
)