Semana 13. Densificación de nubes de puntos
El trabajo de esta semana ha sido buscar la forma de densificar las nubes de puntos de los datasets Goose y Rellis 3d.
He implementado un programa el cual lee los archivos, .bin
o .ply
, de un directorio, y crea nubes de puntos densificadas, en el mismo formato que el archivo de entrada. El programa cuenta con una interfaz gráfica que permite seleccionar los directorios de origen y de destino.
La densificación se realiza mediante la funcion densify_point_cloud()
.
def densify_point_cloud(points: np.ndarray, remissions: np.ndarray,
density_factor: float = 5.0, noise_stddev: float = 0.02) -> tuple[np.ndarray, np.ndarray, np.ndarray, np.ndarray]:
"""
Densifica la nube de puntos sin perder detalle, añadiendo puntos de forma controlada.
"""
num_new_points = int(len(points) * density_factor)
# Seleccionar índices aleatorios para añadir puntos
base_indices = np.random.choice(len(points), num_new_points, replace=True)
# Añadir ruido controlado a los puntos seleccionados
noise_points = points[base_indices] + np.random.normal(0, noise_stddev, (num_new_points, 3))
# Las intensidades de los nuevos puntos son las mismas que las de los puntos seleccionados
noise_remissions = remissions[base_indices]
return points, remissions, noise_points, noise_remissions
La funcion selecciona puntos de la nube original de manera aleatoria y les agrega un poco de ruido, generando nuevos puntos cerca de los puntos originales. Consigueinso una nube más densa.
density_factor
: Contola cuantos puntos adicionales se generan por punto original.
noise_stddev
: Establece la cantidad de cariacion que se agrega a los nuevos puntos.
También he realizar una densificación por interpolación de vecinos. Este metodo tiene el problema de que el tiempo que necesita para el cálculo es demasiado alto.
en este caso la densificación se realiza con la función densify_point_cloud()
pero en este caso es de la siguiente forma:
```python def densify_point_cloud(points: np.ndarray, remissions: np.ndarray, density_factor: float = 5.0, n_neighbors: int = 5) -> Tuple[np.ndarray, np.ndarray, np.ndarray, np.ndarray]: “”” Densifica la nube de puntos utilizando interpolación basada en vecinos más cercanos.
:param points: Nube de puntos original (N, 3)
:param remissions: Intensidades de los puntos originales (N,)
:param density_factor: Factor de densificación (número de nuevos puntos a agregar)
:param n_neighbors: Número de vecinos cercanos para interpolación
:return: Nuevos puntos generados, sus intensidades, y los puntos originales
"""
# Usar NearestNeighbors para encontrar los vecinos más cercanos
nn = NearestNeighbors(n_neighbors=n_neighbors)
nn.fit(points)
# Establecer el número de nuevos puntos a crear
num_new_points = int(len(points) * density_factor)
# Almacenar los puntos y las intensidades generadas
new_points = []
new_remissions = []
for _ in range(num_new_points):
# Elegir un punto aleatorio de la nube de puntos original
index = np.random.randint(0, len(points))
point = points[index]
# Obtener los vecinos más cercanos
distances, indices = nn.kneighbors([point], n_neighbors=n_neighbors)
# Seleccionar un vecino aleatorio entre los más cercanos para interpolar
neighbor_idx = np.random.choice(indices[0])
neighbor_point = points[neighbor_idx]
# Interpolar entre el punto original y el vecino seleccionado
interpolated_point = (point + neighbor_point) / 2 # Promedio de la posición
# Las intensidades de los nuevos puntos serán las medias de las intensidades de los puntos vecinos
interpolated_remission = np.mean(remissions[indices[0]])
# Agregar el nuevo punto y su intensidad
new_points.append(interpolated_point)
new_remissions.append(interpolated_remission)
# Convertir las listas a arrays
new_points = np.array(new_points)
new_remissions = np.array(new_remissions)
# Retornar los puntos originales junto con los nuevos puntos
return points, remissions, new_points, new_remissions
```