-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
0ea3960
commit 07d9e2e
Showing
1 changed file
with
112 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,112 @@ | ||
--- | ||
title: "Semana 13. Densificación de nubes de puntos" | ||
categories: | ||
- Weblog | ||
tags: | ||
- Lidar | ||
- Visor 3d | ||
- Python | ||
- Goose | ||
- Rellis 3d | ||
- Densificación | ||
|
||
--- | ||
|
||
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. | ||
|
||
<figure class="align-center" style="max-width: 100%"> | ||
<img src="{{ site.url }}{{ site.baseurl }}/assets/images/interfazDensificador.png" alt="infaceDens"> | ||
</figure> | ||
|
||
La densificación se realiza mediante la funcion ```densify_point_cloud()```. | ||
```python | ||
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. | ||
|
||
<figure class="align-center" style="max-width: 100%"> | ||
<img src="{{ site.url }}{{ site.baseurl }}/assets/videos/densificacionRuido.gif" alt="densRuido"> | ||
</figure> | ||
|
||
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 | ||
``` | ||
|
||
<figure class="align-center" style="max-width: 100%"> | ||
<img src="{{ site.url }}{{ site.baseurl }}/assets/videos/ddensificacionVecinos.png" alt="densVecinos"> | ||
</figure> |