reconstruct3d 0.1.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- reconstruct3d-0.1.0/.github/workflows/publish.yml +49 -0
- reconstruct3d-0.1.0/.gitignore +33 -0
- reconstruct3d-0.1.0/.python-version +1 -0
- reconstruct3d-0.1.0/CLAUDE.md +203 -0
- reconstruct3d-0.1.0/LICENSE +21 -0
- reconstruct3d-0.1.0/PKG-INFO +416 -0
- reconstruct3d-0.1.0/README.md +380 -0
- reconstruct3d-0.1.0/backend/.gitignore +1 -0
- reconstruct3d-0.1.0/backend/__init__.py +0 -0
- reconstruct3d-0.1.0/backend/app.py +175 -0
- reconstruct3d-0.1.0/camera.example.json +14 -0
- reconstruct3d-0.1.0/camera.json +12 -0
- reconstruct3d-0.1.0/data/.gitkeep +0 -0
- reconstruct3d-0.1.0/docs.md +254 -0
- reconstruct3d-0.1.0/frontend/.gitignore +2 -0
- reconstruct3d-0.1.0/frontend/index.html +12 -0
- reconstruct3d-0.1.0/frontend/package-lock.json +1687 -0
- reconstruct3d-0.1.0/frontend/package.json +20 -0
- reconstruct3d-0.1.0/frontend/src/App.jsx +196 -0
- reconstruct3d-0.1.0/frontend/src/Viewer.jsx +131 -0
- reconstruct3d-0.1.0/frontend/src/api.js +24 -0
- reconstruct3d-0.1.0/frontend/src/main.jsx +10 -0
- reconstruct3d-0.1.0/frontend/src/styles.css +77 -0
- reconstruct3d-0.1.0/frontend/vite.config.js +13 -0
- reconstruct3d-0.1.0/pipeline.py +10 -0
- reconstruct3d-0.1.0/pyproject.toml +81 -0
- reconstruct3d-0.1.0/reconstruct3d/__init__.py +17 -0
- reconstruct3d-0.1.0/reconstruct3d/api.py +218 -0
- reconstruct3d-0.1.0/reconstruct3d/bundle_adjust.py +370 -0
- reconstruct3d-0.1.0/reconstruct3d/calibrate.py +199 -0
- reconstruct3d-0.1.0/reconstruct3d/cgal_mesh/.gitignore +1 -0
- reconstruct3d-0.1.0/reconstruct3d/cgal_mesh/CMakeLists.txt +22 -0
- reconstruct3d-0.1.0/reconstruct3d/cgal_mesh/mesh_reconstruct.cpp +312 -0
- reconstruct3d-0.1.0/reconstruct3d/chunked.py +335 -0
- reconstruct3d-0.1.0/reconstruct3d/cli.py +448 -0
- reconstruct3d-0.1.0/reconstruct3d/core.py +515 -0
- reconstruct3d-0.1.0/reconstruct3d/dense_mvs.py +256 -0
- reconstruct3d-0.1.0/reconstruct3d/init_sfm.py +151 -0
- reconstruct3d-0.1.0/reconstruct3d/mesh.py +99 -0
- reconstruct3d-0.1.0/reconstruct3d/track_sfm.py +253 -0
- reconstruct3d-0.1.0/reconstruct3d/viewer.py +108 -0
- reconstruct3d-0.1.0/uv.lock +2468 -0
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
name: Publish to PyPI
|
|
2
|
+
|
|
3
|
+
# Se dispara solo al empujar un tag de versión (ej. v0.2.0). El tag define la
|
|
4
|
+
# versión publicada (la lee hatch-vcs). Para publicar: git tag v0.2.0 && git push --tags
|
|
5
|
+
on:
|
|
6
|
+
push:
|
|
7
|
+
tags:
|
|
8
|
+
- "v*"
|
|
9
|
+
|
|
10
|
+
jobs:
|
|
11
|
+
build:
|
|
12
|
+
name: Construir distribución
|
|
13
|
+
runs-on: ubuntu-latest
|
|
14
|
+
steps:
|
|
15
|
+
- uses: actions/checkout@v4
|
|
16
|
+
with:
|
|
17
|
+
# hatch-vcs necesita el historial completo + tags para calcular la versión.
|
|
18
|
+
fetch-depth: 0
|
|
19
|
+
|
|
20
|
+
- uses: actions/setup-python@v5
|
|
21
|
+
with:
|
|
22
|
+
python-version: "3.12"
|
|
23
|
+
|
|
24
|
+
- name: Build (sdist + wheel)
|
|
25
|
+
run: |
|
|
26
|
+
python -m pip install --upgrade build
|
|
27
|
+
python -m build
|
|
28
|
+
|
|
29
|
+
- uses: actions/upload-artifact@v4
|
|
30
|
+
with:
|
|
31
|
+
name: dist
|
|
32
|
+
path: dist/
|
|
33
|
+
|
|
34
|
+
publish:
|
|
35
|
+
name: Publicar en PyPI
|
|
36
|
+
needs: build
|
|
37
|
+
runs-on: ubuntu-latest
|
|
38
|
+
# Debe coincidir con el "Environment name" del Trusted Publisher en PyPI.
|
|
39
|
+
environment: pypi
|
|
40
|
+
permissions:
|
|
41
|
+
# OIDC: token efímero para Trusted Publishing. SIN tokens ni passwords.
|
|
42
|
+
id-token: write
|
|
43
|
+
steps:
|
|
44
|
+
- uses: actions/download-artifact@v4
|
|
45
|
+
with:
|
|
46
|
+
name: dist
|
|
47
|
+
path: dist/
|
|
48
|
+
|
|
49
|
+
- uses: pypa/gh-action-pypi-publish@release/v1
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
# Python
|
|
2
|
+
__pycache__/
|
|
3
|
+
*.py[cod]
|
|
4
|
+
*.egg-info/
|
|
5
|
+
.pytest_cache/
|
|
6
|
+
.venv/
|
|
7
|
+
venv*/
|
|
8
|
+
.env
|
|
9
|
+
.venv
|
|
10
|
+
|
|
11
|
+
# Build artifacts
|
|
12
|
+
build/
|
|
13
|
+
dist/
|
|
14
|
+
|
|
15
|
+
# IDE
|
|
16
|
+
.vscode/
|
|
17
|
+
.idea/
|
|
18
|
+
|
|
19
|
+
# Input videos (heavy binaries, keep the folder via .gitkeep)
|
|
20
|
+
data/*
|
|
21
|
+
!data/.gitkeep
|
|
22
|
+
!data/README.md
|
|
23
|
+
|
|
24
|
+
# Runtime outputs (regenerated by the pipeline)
|
|
25
|
+
outputs/
|
|
26
|
+
*.pkl
|
|
27
|
+
*.npy
|
|
28
|
+
*.ply
|
|
29
|
+
!pruebas1/*.ply
|
|
30
|
+
|
|
31
|
+
# OS noise
|
|
32
|
+
.DS_Store
|
|
33
|
+
Thumbs.db
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
3.10
|
|
@@ -0,0 +1,203 @@
|
|
|
1
|
+
# CLAUDE.md — Contexto del proyecto para agentes de IA
|
|
2
|
+
|
|
3
|
+
> Este archivo orienta a Claude Code (y otros agentes) sobre **qué es** este
|
|
4
|
+
> proyecto, **cómo está organizado** y **cómo trabajar en él** sin romper nada.
|
|
5
|
+
> Léelo antes de proponer cambios.
|
|
6
|
+
|
|
7
|
+
## Qué es (y qué NO es)
|
|
8
|
+
|
|
9
|
+
Pipeline **offline** de reconstrucción 3D a partir de un video monocular. El
|
|
10
|
+
nombre del repo dice "SLAM", pero técnicamente esto es **Structure-from-Motion
|
|
11
|
+
(SfM) incremental + densificación MVS-lite**, no SLAM:
|
|
12
|
+
|
|
13
|
+
- **NO** es tiempo real, **NO** hay loop-closure ni mapeo online.
|
|
14
|
+
- Procesa un video ya grabado por **etapas secuenciales** que escriben artefactos
|
|
15
|
+
a disco.
|
|
16
|
+
- El "tracking" de cámara se hace con **PnP** (`cv2.solvePnPRansac`), no con un
|
|
17
|
+
filtro recursivo.
|
|
18
|
+
|
|
19
|
+
El emparejamiento de features tiene **3 front-ends intercambiables** (no uno
|
|
20
|
+
solo): `sift` (default), `orb`, y `spglue` (SuperPoint + LightGlue, requiere
|
|
21
|
+
torch). LightGlue es **opcional**, no el camino por defecto.
|
|
22
|
+
|
|
23
|
+
## Arquitectura: el pipeline de 6 etapas
|
|
24
|
+
|
|
25
|
+
Todas las etapas comparten un **directorio de salida** (`outputs/<frontend>/`)
|
|
26
|
+
donde leen/escriben artefactos. El orden importa: cada etapa consume lo que
|
|
27
|
+
produjo la anterior.
|
|
28
|
+
|
|
29
|
+
```
|
|
30
|
+
video.mp4
|
|
31
|
+
│
|
|
32
|
+
▼ [1] core.py ............ extrae features + matrices esenciales por pares
|
|
33
|
+
sfm_data.pkl
|
|
34
|
+
│
|
|
35
|
+
▼ [2] init_sfm.py ........ triangula el "par semilla" (mejor baseline)
|
|
36
|
+
map_state.npy + init_cloud.ply
|
|
37
|
+
│
|
|
38
|
+
▼ [3] track_sfm.py ....... registro incremental PnP + BA local + fusión
|
|
39
|
+
tracked_cloud.ply (nube rala/sparse)
|
|
40
|
+
│
|
|
41
|
+
▼ [4] bundle_adjust.py ... BA GLOBAL opcional (refina todo el mapa)
|
|
42
|
+
map_state.npy (refinado)
|
|
43
|
+
│
|
|
44
|
+
▼ [5] dense_mvs.py ....... densificación stereo SGBM + fusión multi-vista
|
|
45
|
+
dense_cloud.ply (nube densa)
|
|
46
|
+
│
|
|
47
|
+
▼ [6] viewer.py .......... visor POV interactivo (proyecta puntos sobre video)
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
### Estructura de paquete (importante)
|
|
51
|
+
|
|
52
|
+
El código se reorganizó como **paquete instalable `reconstruct3d/`**. Los módulos
|
|
53
|
+
de la tabla viven ahora en `reconstruct3d/<módulo>.py` (no en la raíz), con
|
|
54
|
+
**imports absolutos** `from reconstruct3d.X import ...`. Piezas nuevas:
|
|
55
|
+
|
|
56
|
+
- `reconstruct3d/api.py` — **API de alto nivel** (clase `Pipeline` con callback
|
|
57
|
+
`on_event` para progreso). Es la forma recomendada de usar la librería desde
|
|
58
|
+
código; `reconstruct3d/__init__.py` exporta `Pipeline`, `run_all`, `CameraConfig`.
|
|
59
|
+
- `reconstruct3d/cli.py` — el orquestador CLI (antes `pipeline.py`). El `pipeline.py`
|
|
60
|
+
de la raíz es solo un **shim** `from reconstruct3d.cli import main`. Console script
|
|
61
|
+
instalado: `reconstruct3d`.
|
|
62
|
+
- `reconstruct3d/cgal_mesh/` — el programa C++ se movió aquí (mesh.py lo localiza
|
|
63
|
+
vía `dirname(__file__)`).
|
|
64
|
+
- `backend/` (FastAPI) y `frontend/` (Vite+React+Three.js) — **demo**, NO forman
|
|
65
|
+
parte del paquete publicado.
|
|
66
|
+
- `pyproject.toml` — paquete con hatchling. **torch/lightglue NO van en deps base**
|
|
67
|
+
(solo en el extra `spglue`), porque lightglue no está en PyPI y torch es pesado.
|
|
68
|
+
Para dev local, `[tool.uv.sources]` resuelve lightglue desde git.
|
|
69
|
+
|
|
70
|
+
### Mapa de archivos
|
|
71
|
+
|
|
72
|
+
| Archivo | Rol | Entradas → Salidas |
|
|
73
|
+
|---|---|---|
|
|
74
|
+
| [pipeline.py](pipeline.py) | **Orquestador CLI**. Punto de entrada único; subcomandos `extract/init/track/ba/dense/view/all`. | — |
|
|
75
|
+
| [core.py](core.py) | Config de cámara, clase `Features`, front-ends (`SiftFrontEnd`, `OrbFrontEnd`, `SuperPointLightGlueFrontEnd`), `SfMDatabase`, `filter_triangulation`. **Módulo base que todos importan.** | video → `sfm_data.pkl` |
|
|
76
|
+
| [init_sfm.py](init_sfm.py) | Selección de par semilla + triangulación inicial. Define `export_ply`. | `sfm_data.pkl` → `map_state.npy`, `init_cloud.ply` |
|
|
77
|
+
| [track_sfm.py](track_sfm.py) | Registro incremental de cámaras (PnP) + inyección de puntos nuevos. | `map_state.npy` → `tracked_cloud.ply` |
|
|
78
|
+
| [bundle_adjust.py](bundle_adjust.py) | `run_local_ba` (ventana, usado por track), `run_bundle_adjustment` (global), `fuse_map_points`. | `map_state.npy` → `map_state.npy` |
|
|
79
|
+
| [dense_mvs.py](dense_mvs.py) | MVS de dos vistas (rectify + StereoSGBM) + fusión por votación de vóxel. **Paralelizado** (`jobs`). | `map_state.npy` + video → `dense_cloud.ply` |
|
|
80
|
+
| [viewer.py](viewer.py) | Visor interactivo OpenCV (sliders de frame y opacidad). | `map_state.npy` + video |
|
|
81
|
+
| [calibrate.py](calibrate.py) | Calibración de `K` desde un video de tablero (`cv2.calibrateCamera`). Modo automático e interactivo. Escribe/crea `camera.json`. | video tablero → `camera.json` |
|
|
82
|
+
| [chunked.py](chunked.py) | Reconstrucción por fragmentos solapados (procesos en paralelo) + alineación Sim(3) por Umeyama sobre centros de cámara compartidos + fusión. | video → `merged_cloud.ply`, `merged_state.npy` |
|
|
83
|
+
| [mesh.py](mesh.py) + [cgal_mesh/](cgal_mesh/) | Mallado de la nube densa con **CGAL** (C++). `mesh.py` compila el binario bajo demanda (CMake) y lo invoca; `mesh_reconstruct.cpp` hace denoise + Advancing Front / Poisson. | `dense_cloud.ply` → `mesh.ply` |
|
|
84
|
+
|
|
85
|
+
### Estructuras de datos clave
|
|
86
|
+
|
|
87
|
+
- **`CameraConfig`** (core.py): intrínsecos `K`, `dist_coeffs`, `PROC_SIZE`.
|
|
88
|
+
Parametrizable y serializable (`to_dict`/`from_dict`/`from_json`). `from_dict`
|
|
89
|
+
acepta K explícita o el atajo `fx/fy/cx/cy` + `width/height`.
|
|
90
|
+
- **`Features`** (core.py): `pts (N,2)`, `descriptors`, `colors (N,3 BGR)`,
|
|
91
|
+
`scores`, `image_size`. Serializada en `sfm_data.pkl` vía pickle.
|
|
92
|
+
- **`SfMDatabase`** (core.py / `sfm_data.pkl`): `features`, `pairwise`,
|
|
93
|
+
`frontend_name`, **`camera`** (dict de `CameraConfig.to_dict()`). `get_camera()`
|
|
94
|
+
devuelve la `CameraConfig` persistida.
|
|
95
|
+
- **`map3d`** (dict en `map_state.npy`, cargado con `np.load(..., allow_pickle=True).item()`):
|
|
96
|
+
- `points (M,3)`, `colors (M,3)`
|
|
97
|
+
- `poses`: `{frame_id: matriz 4x4 world→cam}`
|
|
98
|
+
- `obs`: `{frame_id: {kp_idx: punto3d_idx}}` — la tabla de observaciones que
|
|
99
|
+
conecta keypoints 2D con puntos 3D. **Es el corazón del estado**; BA y
|
|
100
|
+
fusión la reindexan.
|
|
101
|
+
- `frontend`: nombre del front-end usado.
|
|
102
|
+
- `camera`: dict de intrínsecos (lo copia `init` desde la DB; lo leen las etapas
|
|
103
|
+
que solo cargan map_state: `dense`, `view`).
|
|
104
|
+
|
|
105
|
+
## Comandos (con uv)
|
|
106
|
+
|
|
107
|
+
`uv` gestiona el entorno. **No uses `pip` ni venvs manuales.**
|
|
108
|
+
|
|
109
|
+
```bash
|
|
110
|
+
uv sync # instala dependencias base (sift/orb)
|
|
111
|
+
uv sync --extra spglue # + torch/torchvision/lightglue (para --frontend spglue)
|
|
112
|
+
|
|
113
|
+
# Pipeline completo end-to-end:
|
|
114
|
+
uv run python pipeline.py all data/video.mp4
|
|
115
|
+
uv run python pipeline.py all data/video.mp4 --frontend spglue --no-dense
|
|
116
|
+
|
|
117
|
+
# Calibración / paralelización / videos largos:
|
|
118
|
+
uv run python pipeline.py calibrate data/calib.mp4 --board 9x6 # crea camera.json
|
|
119
|
+
uv run python pipeline.py all data/video.mp4 --jobs 8 # paraleliza
|
|
120
|
+
uv run python pipeline.py chunked data/video.mp4 --chunk 80 --overlap 20 --chunk-jobs 4
|
|
121
|
+
uv run python pipeline.py mesh --method afront # malla CGAL (requiere CGAL nativo)
|
|
122
|
+
|
|
123
|
+
# Etapa por etapa (mismo --out implícito = outputs/<frontend>/):
|
|
124
|
+
uv run python pipeline.py extract data/video.mp4
|
|
125
|
+
uv run python pipeline.py init
|
|
126
|
+
uv run python pipeline.py track
|
|
127
|
+
uv run python pipeline.py ba # opcional pero recomendado
|
|
128
|
+
uv run python pipeline.py dense data/video.mp4
|
|
129
|
+
uv run python pipeline.py view data/video.mp4
|
|
130
|
+
```
|
|
131
|
+
|
|
132
|
+
Los scripts individuales (`core.py`, etc.) **siguen funcionando** vía
|
|
133
|
+
`uv run python core.py video.mp4 --out ...`; el orquestador solo los encadena.
|
|
134
|
+
|
|
135
|
+
## Convenciones del código
|
|
136
|
+
|
|
137
|
+
- **Idioma:** comentarios, docstrings y mensajes de consola en **español**.
|
|
138
|
+
Los nombres de variables/funciones en inglés. Mantén esa mezcla.
|
|
139
|
+
- **Comentarios densos y explicativos:** el código existente comenta el *porqué*
|
|
140
|
+
de cada decisión geométrica/numérica (chiralidad, baseline, gauge del BA…).
|
|
141
|
+
Iguala ese nivel; no añadas comentarios triviales.
|
|
142
|
+
- **Convención de poses:** todas las matrices `4x4` son **world→cam**. El centro
|
|
143
|
+
de cámara es `-R.T @ t`. Respétalo en todo el código nuevo.
|
|
144
|
+
- **Front-ends:** para añadir uno, hereda de `FrontEnd` (core.py), implementa
|
|
145
|
+
`extract`/`match` y regístralo en `_FRONTEND_REGISTRY`. Los imports pesados
|
|
146
|
+
(torch) van **lazy** dentro de `__init__`.
|
|
147
|
+
- **Salida vía `export_ply`** (init_sfm.py): la nube se exporta **centrada** en
|
|
148
|
+
la mediana y los colores se guardan BGR→RGB. Las cámaras van en rojo.
|
|
149
|
+
|
|
150
|
+
## Gotchas / cosas que romper sin querer
|
|
151
|
+
|
|
152
|
+
- **Pickles atados al layout.** `sfm_data.pkl` guarda objetos `Features`; los
|
|
153
|
+
scripts hacen `sys.modules['__main__'].Features = Features` para poder
|
|
154
|
+
deserializarlos. Si reorganizas `core.py` como paquete, los pickles viejos
|
|
155
|
+
dejan de cargar (`ModuleNotFoundError`). Los artefactos en `outputs/` del repo
|
|
156
|
+
son de un layout empaquetado anterior y **no cargan con los scripts planos
|
|
157
|
+
actuales** — regenéralos con `extract`.
|
|
158
|
+
- **Intrínsecos por dispositivo.** `K` depende de la cámara que grabó. Se
|
|
159
|
+
configura con `--camera tu_camara.json` en `extract`/`all` (ver
|
|
160
|
+
`camera.example.json`), o se genera con `calibrate`. Se persiste en la DB +
|
|
161
|
+
map_state, propagándose a todas las etapas. **No vuelvas a hardcodear K**. `K` y
|
|
162
|
+
`PROC_SIZE` deben corresponder a la MISMA resolución (el frame se redimensiona a
|
|
163
|
+
`PROC_SIZE` antes de extraer). La resolución de calibración (`proc_size`) debe
|
|
164
|
+
tener el punto principal ≈ centro: si `cx,cy` no caen cerca de `W/2,H/2`, la
|
|
165
|
+
resolución es incorrecta.
|
|
166
|
+
- **Paralelismo y thread-safety.** Extracción/matching (core) y densificación
|
|
167
|
+
(dense_mvs) usan `ThreadPoolExecutor` con `--jobs`. Los objetos de OpenCV
|
|
168
|
+
(SIFT/ORB/BFMatcher/StereoSGBM) **no son thread-safe compartidos** → cada hilo
|
|
169
|
+
crea el suyo vía `threading.local` (`tls_frontend`, `_tls_sgbm`). Si añades una
|
|
170
|
+
etapa paralela, replica ese patrón; no compartas el detector entre hilos. Para
|
|
171
|
+
`spglue` el paralelismo se fuerza a 1 (`resolve_workers`). Los resultados
|
|
172
|
+
paralelos son idénticos al modo secuencial (verificado).
|
|
173
|
+
- **Mallado nativo (CGAL).** El paso `mesh` NO es Python puro: usa un binario C++
|
|
174
|
+
(`cgal_mesh/mesh_reconstruct.cpp`) que enlaza **CGAL** (header-only) + boost/gmp/
|
|
175
|
+
mpfr/eigen, compilado con CMake. `mesh.py` lo compila bajo demanda en
|
|
176
|
+
`cgal_mesh/build/` la primera vez. Si CGAL no está, `all` **omite** el mallado
|
|
177
|
+
con un aviso (no falla). CGAL 6.x cambió APIs respecto a 5.x: `property_map`
|
|
178
|
+
devuelve `std::optional`, los parámetros usan `CGAL::parameters::`. Advancing
|
|
179
|
+
Front conserva el color (vértices = puntos de entrada); Poisson genera vértices
|
|
180
|
+
nuevos y transfiere color por KD-tree (vecino más cercano).
|
|
181
|
+
- **Chunking y alineación.** `chunked.py` reconstruye fragmentos en **procesos**
|
|
182
|
+
separados (`ProcessPoolExecutor`, start method `spawn` en macOS → el worker
|
|
183
|
+
`_run_chunk_worker` y su `cfg` deben ser top-level/picklables). La alineación
|
|
184
|
+
necesita **≥4 frames de solape no degenerados**: con <4 la Sim(3) de Umeyama
|
|
185
|
+
queda subdeterminada (ajusta el solape pero no recupera la rotación global).
|
|
186
|
+
Todos los chunks muestrean la MISMA rejilla global de `k_skip` para que los
|
|
187
|
+
frames del solape tengan índices absolutos idénticos.
|
|
188
|
+
- **Reset del estado.** Si `track` se estanca, vuelve a correr `init` antes de
|
|
189
|
+
reintentar (reinicia `map_state.npy`).
|
|
190
|
+
- **`req.txt` es legacy** (un `pip freeze` inflado con open3d/dash/sklearn que el
|
|
191
|
+
código NO usa). La fuente de verdad de dependencias es `pyproject.toml`.
|
|
192
|
+
- **Escenas degeneradas.** Paneos sobre superficies planas o arranques de
|
|
193
|
+
casi-rotación pura no producen seed viable (paralaje ~0). Usa `--start-seconds`
|
|
194
|
+
para saltar arranques malos.
|
|
195
|
+
- **macOS/Wayland + visor.** `viewer.py` abre ventanas OpenCV HighGUI; en
|
|
196
|
+
entornos headless o Wayland puede fallar. En Arch/Wayland: `env -u WAYLAND_DISPLAY ...`.
|
|
197
|
+
|
|
198
|
+
## Carpetas
|
|
199
|
+
|
|
200
|
+
- `data/` — videos de entrada (ignorada por git salvo `.gitkeep`).
|
|
201
|
+
- `outputs/` — artefactos regenerables (ignorada por git).
|
|
202
|
+
- `pruebas1/` — **scripts experimentales antiguos** (SfM/VO previos). No forman
|
|
203
|
+
parte del pipeline actual; no los uses como referencia de la arquitectura viva.
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 BlackMonkcr
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|