feat(ml): auto-commit con 7 cambios
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -105,6 +105,8 @@ report `0079`).
|
|||||||
| [comfyui_image_to_3d_oneshot_py_pipelines](../../python/functions/pipelines/comfyui_image_to_3d_oneshot.md) | `image_to_3d_oneshot(image_path, *, server, variant='mini', dest=None, wait_timeout, **gen) -> dict` | **Pipeline** imagen en disco → malla GLB en una llamada: upload + build + submit + wait + fetch. Promoción de la secuencia (issue 0087). Impuro. |
|
| [comfyui_image_to_3d_oneshot_py_pipelines](../../python/functions/pipelines/comfyui_image_to_3d_oneshot.md) | `image_to_3d_oneshot(image_path, *, server, variant='mini', dest=None, wait_timeout, **gen) -> dict` | **Pipeline** imagen en disco → malla GLB en una llamada: upload + build + submit + wait + fetch. Promoción de la secuencia (issue 0087). Impuro. |
|
||||||
| [comfyui_text_to_3d_oneshot_py_pipelines](../../python/functions/pipelines/comfyui_text_to_3d_oneshot.md) | `text_to_3d_oneshot(prompt, *, server, ckpt_name='v1-5-pruned-emaonly.safetensors', negative='', textured=False, variant='mini', dest=None, ...) -> dict` | **Pipeline** prompt de texto → malla 3D GLB en una llamada: txt2img (SD) + fetch + upload + build 3D (nativo o `textured=True` multi-vista PBR) + submit + wait + fetch_mesh. Promoción de la secuencia texto→imagen→3D (issue 0087). Impuro. |
|
| [comfyui_text_to_3d_oneshot_py_pipelines](../../python/functions/pipelines/comfyui_text_to_3d_oneshot.md) | `text_to_3d_oneshot(prompt, *, server, ckpt_name='v1-5-pruned-emaonly.safetensors', negative='', textured=False, variant='mini', dest=None, ...) -> dict` | **Pipeline** prompt de texto → malla 3D GLB en una llamada: txt2img (SD) + fetch + upload + build 3D (nativo o `textured=True` multi-vista PBR) + submit + wait + fetch_mesh. Promoción de la secuencia texto→imagen→3D (issue 0087). Impuro. |
|
||||||
| [comfyui_build_textured_3d_multiview_workflow_py_ml](../../python/functions/ml/comfyui_build_textured_3d_multiview_workflow.md) | `build_textured_3d_multiview_workflow(image_name, *, ckpt='hunyuan3d-dit-v2-mv.safetensors', views=6, octree=384, max_faces=50000, upscale_model='4x_foolhardy_Remacri.pth') -> dict` | Builder imagen→malla 3D **con textura PBR** vía el wrapper Hunyuan3DWrapper (kijai): 4/6 vistas + delight + sample multi-vista + upscale Remacri + bake sobre UV (19 nodos). Cobertura de atlas 32.93% (report 0082). **Pura**. En 8 GB ejecutar en 2 fases (shape→`/free`→paint). |
|
| [comfyui_build_textured_3d_multiview_workflow_py_ml](../../python/functions/ml/comfyui_build_textured_3d_multiview_workflow.md) | `build_textured_3d_multiview_workflow(image_name, *, ckpt='hunyuan3d-dit-v2-mv.safetensors', views=6, octree=384, max_faces=50000, upscale_model='4x_foolhardy_Remacri.pth') -> dict` | Builder imagen→malla 3D **con textura PBR** vía el wrapper Hunyuan3DWrapper (kijai): 4/6 vistas + delight + sample multi-vista + upscale Remacri + bake sobre UV (19 nodos). Cobertura de atlas 32.93% (report 0082). **Pura**. En 8 GB ejecutar en 2 fases (shape→`/free`→paint). |
|
||||||
|
| [comfyui_simplify_mesh_py_ml](../../python/functions/ml/comfyui_simplify_mesh.md) | `simplify_mesh(in_path, *, target_faces=80000, weld=True, out_path=None) -> dict` | **Post-proceso**: decima un GLB/OBJ/PLY denso (suelda cube-soup + quadric edge collapse de pymeshlab), conservando vertex colors o textura+UV. 964k→80k caras, 34.7→1.43 MB medido (report 0090). `weld=True` es clave: sin él la cube-soup de `VoxelToMeshBasic` no decima. Impura (trimesh+pymeshlab+scipy). |
|
||||||
|
| [comfyui_make_watertight_py_ml](../../python/functions/ml/comfyui_make_watertight.md) | `make_watertight(in_path, *, method='voxel', pitch=None, out_path=None) -> dict` | **Post-proceso**: hace estanca una malla. `method='voxel'` (voxeliza+fill+marching cubes) garantiza `is_watertight=True` a costa de más caras y de descartar la apariencia; `method='repair'` (fill_holes+fix_normals) conserva detalle pero no garantiza estanqueidad. La vía de raíz es `VoxelToMesh surface net` (report 0088). Impura. |
|
||||||
|
|
||||||
### Por la UI web (CDP) — dominio `browser`
|
### Por la UI web (CDP) — dominio `browser`
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,82 @@
|
|||||||
|
---
|
||||||
|
name: comfyui_make_watertight
|
||||||
|
kind: function
|
||||||
|
lang: py
|
||||||
|
domain: ml
|
||||||
|
version: "1.0.0"
|
||||||
|
purity: impure
|
||||||
|
signature: "def comfyui_make_watertight(in_path: str, *, method: str = \"voxel\", pitch: float | None = None, out_path: str | None = None) -> dict"
|
||||||
|
description: "Hace estanca (watertight) una malla 3D GLB/OBJ/PLY de ComfyUI/Hunyuan3D. method='voxel' (default) voxeliza el solido, rellena el interior y reconstruye con marching cubes (trimesh) -> is_watertight=True garantizado, a costa de mas caras y de descartar la apariencia; necesita scikit-image. method='repair' hace limpieza ligera (trimesh.repair fill_holes + fix_normals + fix_winding) conservando el detalle, pero no garantiza estanqueidad en mallas muy rotas. La via de raiz es generar con el nodo VoxelToMesh algorithm='surface net' (report 0088). Impura: lee y escribe en disco."
|
||||||
|
tags: [comfyui, 3d, mesh, hunyuan3d, watertight, voxel, remesh, trimesh, ml]
|
||||||
|
uses_functions: []
|
||||||
|
uses_types: []
|
||||||
|
returns: []
|
||||||
|
returns_optional: false
|
||||||
|
error_type: error_go_core
|
||||||
|
imports: []
|
||||||
|
params:
|
||||||
|
- name: in_path
|
||||||
|
desc: "Ruta de la malla de entrada (.glb/.obj/.ply/.gltf/.stl/.off). Scene GLB con varias geometrias se concatena en una sola malla."
|
||||||
|
- name: method
|
||||||
|
desc: "'voxel' (default, garantiza is_watertight=True via voxeliza+fill+marching cubes) o 'repair' (fill_holes + fix_normals, conserva detalle pero no siempre estanca). keyword-only."
|
||||||
|
- name: pitch
|
||||||
|
desc: "Solo para method='voxel'. Tamano de voxel absoluto. Si None, se calcula como diagonal_bbox / 200. Mas pequeno = mas caras y mas detalle, mas lento. keyword-only."
|
||||||
|
- name: out_path
|
||||||
|
desc: "Ruta de salida. Si None, escribe '<in>_watertight.glb' junto al original (NO sobrescribe). keyword-only."
|
||||||
|
output: "dict {ok, was_watertight, is_watertight, out_path, method, pitch, out_faces, error}. was/is_watertight = estanqueidad antes/despues medida con trimesh.is_watertight. out_faces = caras del resultado (el voxel-remesh suele aumentarlas). Si falla, ok=False y error explica (dependencia ausente, method invalido, archivo no existe, carga o remesh)."
|
||||||
|
tested: false
|
||||||
|
tests: []
|
||||||
|
test_file_path: ""
|
||||||
|
file_path: "python/functions/ml/comfyui_make_watertight.py"
|
||||||
|
---
|
||||||
|
|
||||||
|
## Ejemplo
|
||||||
|
|
||||||
|
```python
|
||||||
|
import sys, os
|
||||||
|
sys.path.insert(0, os.path.join(os.environ["HOME"], "fn_registry", "python", "functions"))
|
||||||
|
from ml.comfyui_make_watertight import comfyui_make_watertight
|
||||||
|
|
||||||
|
# Cierra una malla decimada no estanca (80k caras) por voxel-remesh.
|
||||||
|
res = comfyui_make_watertight(
|
||||||
|
"/tmp/character_simplified.glb",
|
||||||
|
method="voxel",
|
||||||
|
out_path="/tmp/character_watertight.glb",
|
||||||
|
)
|
||||||
|
# res == {"ok": True, "was_watertight": False, "is_watertight": True,
|
||||||
|
# "method": "voxel", "pitch": 0.01596, "out_faces": 250672,
|
||||||
|
# "out_path": "/tmp/character_watertight.glb", "error": ""}
|
||||||
|
```
|
||||||
|
|
||||||
|
Lanzar con el python del venv del registry (import de arriba o heredoc). `./fn run`
|
||||||
|
directo no aplica: la firma usa `*` (keyword-only), no soportado por el runner de `fn run`.
|
||||||
|
|
||||||
|
## Cuando usarla
|
||||||
|
|
||||||
|
Cuando una malla de ComfyUI/Hunyuan3D sale NO estanca (`is_watertight=False`, tipico
|
||||||
|
del nodo DEPRECATED `VoxelToMeshBasic`) y la necesitas cerrada para imprimir en 3D,
|
||||||
|
calcular volumen, boolean ops o simulacion. Usa `method="voxel"` cuando exiges
|
||||||
|
estanqueidad garantizada (la silueta se conserva, el detalle fino se suaviza).
|
||||||
|
Usa `method="repair"` cuando la malla solo tiene huecos pequenos y quieres conservar
|
||||||
|
caras/detalle. Para malla ligera Y estanca, decima antes con `comfyui_simplify_mesh`
|
||||||
|
y luego pasa el resultado por aqui con `method="voxel"`.
|
||||||
|
|
||||||
|
## Gotchas
|
||||||
|
|
||||||
|
- Impura: lee `in_path` y escribe `out_path`. Nunca sobrescribe el original salvo
|
||||||
|
que apuntes `out_path` a el.
|
||||||
|
- `method="voxel"` DESCARTA la apariencia (UV / vertex colors): el marching cubes
|
||||||
|
genera geometria nueva sin atributos. Si quieres color, aplicalo despues del
|
||||||
|
remesh, o usa la via de raiz (`VoxelToMesh surface net`) que preserva el flujo de
|
||||||
|
texturizado.
|
||||||
|
- `method="voxel"` necesita `scikit-image` en el venv (marching cubes). Sin el
|
||||||
|
devuelve ok=False con la instruccion `uv add scikit-image`.
|
||||||
|
- `method="repair"` NO garantiza `is_watertight=True`: en mallas muy rotas
|
||||||
|
(cube-soup con muchos huecos grandes) devuelve `is_watertight=False`. Es
|
||||||
|
esperado; para garantia usa `method="voxel"`.
|
||||||
|
- El voxel-remesh aumenta el numero de caras (densidad del marching cubes). Si
|
||||||
|
necesitas ligero Y estanco, vuelve a decimar el resultado con
|
||||||
|
`comfyui_simplify_mesh` (el report 0088 logra 80k caras + estanco re-cerrando).
|
||||||
|
- `euler_number` puede quedar negativo aunque sea estanco: indica genus alto real
|
||||||
|
(tuneles de la geometria), no un fallo. Estanco != genus 0.
|
||||||
|
- `pitch` muy pequeno sobre mallas grandes es lento (corre en CPU, no usa VRAM).
|
||||||
@@ -0,0 +1,133 @@
|
|||||||
|
"""Hace estanca (watertight) una malla 3D GLB/OBJ/PLY.
|
||||||
|
|
||||||
|
Post-proceso de las mallas de ComfyUI/Hunyuan3D producidas con el nodo
|
||||||
|
VoxelToMeshBasic (DEPRECATED), que genera mallas NO estancas (is_watertight=False):
|
||||||
|
crea 4 vertices nuevos por cara expuesta sin soldarlos, dejando huecos y bordes
|
||||||
|
non-manifold. Dos metodos:
|
||||||
|
|
||||||
|
- method="voxel" (default, garantiza is_watertight=True): voxeliza el solido,
|
||||||
|
rellena el interior y reconstruye la superficie con marching cubes
|
||||||
|
(trimesh voxelized(pitch).fill().marching_cubes). Produce una malla cerrada por
|
||||||
|
construccion. Coste: mas caras (densidad del marching cubes) y descarta la
|
||||||
|
apariencia (UV/vertex colors). Necesita scikit-image (marching cubes).
|
||||||
|
- method="repair": limpieza ligera con trimesh.repair (fix_winding + fill_holes +
|
||||||
|
fix_normals + merge_vertices). Conserva el detalle y las caras, pero NO garantiza
|
||||||
|
estanqueidad en mallas muy rotas (solo cierra huecos pequenos).
|
||||||
|
|
||||||
|
La via de RAIZ (no este post-proceso) es generar con el nodo VoxelToMesh
|
||||||
|
algorithm='surface net', que da malla manifold cerrada sin reparar (ver report 0088).
|
||||||
|
|
||||||
|
Impura: lee y escribe archivos en disco. Requiere trimesh (+ scikit-image para voxel).
|
||||||
|
"""
|
||||||
|
import os
|
||||||
|
|
||||||
|
import numpy as np
|
||||||
|
|
||||||
|
|
||||||
|
def _load_mesh(path):
|
||||||
|
import trimesh
|
||||||
|
|
||||||
|
obj = trimesh.load(path, process=False)
|
||||||
|
if isinstance(obj, trimesh.Scene):
|
||||||
|
obj = trimesh.util.concatenate(list(obj.geometry.values()))
|
||||||
|
return obj
|
||||||
|
|
||||||
|
|
||||||
|
def comfyui_make_watertight(
|
||||||
|
in_path: str,
|
||||||
|
*,
|
||||||
|
method: str = "voxel",
|
||||||
|
pitch: float | None = None,
|
||||||
|
out_path: str | None = None,
|
||||||
|
) -> dict:
|
||||||
|
"""Hace estanca una malla GLB/OBJ/PLY por voxel-remesh o reparacion.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
in_path: ruta de la malla de entrada (.glb/.obj/.ply/.gltf/.stl/.off).
|
||||||
|
method: "voxel" (default, garantiza is_watertight=True via voxeliza+fill+
|
||||||
|
marching cubes) o "repair" (fill_holes + fix_normals, conserva detalle
|
||||||
|
pero no siempre estanca). keyword-only.
|
||||||
|
pitch: solo para method="voxel". Tamano de voxel absoluto. Si None, se
|
||||||
|
calcula como diagonal_bbox / 200 (mas fino = mas caras y detalle).
|
||||||
|
keyword-only.
|
||||||
|
out_path: ruta de salida. Si None, escribe "<in>_watertight.glb" junto al
|
||||||
|
original. keyword-only.
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
dict {ok, was_watertight, is_watertight, out_path, method, pitch, out_faces,
|
||||||
|
error}. was/is_watertight = estanqueidad antes/despues (trimesh). Si falla,
|
||||||
|
ok=False y error explica.
|
||||||
|
"""
|
||||||
|
base_err = {
|
||||||
|
"ok": False, "was_watertight": None, "is_watertight": None,
|
||||||
|
"out_path": "", "method": method, "pitch": None, "out_faces": 0,
|
||||||
|
}
|
||||||
|
try:
|
||||||
|
import trimesh
|
||||||
|
except ImportError as exc:
|
||||||
|
return {**base_err, "error": f"falta trimesh: {exc}. cd python && uv add trimesh"}
|
||||||
|
|
||||||
|
if method not in ("voxel", "repair"):
|
||||||
|
return {**base_err, "error": f"method '{method}' invalido (usa 'voxel' o 'repair')"}
|
||||||
|
if not os.path.exists(in_path):
|
||||||
|
return {**base_err, "error": f"no existe el archivo de entrada: {in_path!r}"}
|
||||||
|
if out_path is None:
|
||||||
|
out_path = os.path.splitext(in_path)[0] + "_watertight.glb"
|
||||||
|
|
||||||
|
try:
|
||||||
|
mesh = _load_mesh(in_path)
|
||||||
|
except Exception as exc:
|
||||||
|
return {**base_err, "error": f"no se pudo cargar la malla {in_path!r}: {exc}"}
|
||||||
|
was = bool(mesh.is_watertight)
|
||||||
|
|
||||||
|
try:
|
||||||
|
if method == "voxel":
|
||||||
|
m = mesh.copy()
|
||||||
|
m.merge_vertices()
|
||||||
|
if pitch is None:
|
||||||
|
diag = float(np.linalg.norm(m.extents))
|
||||||
|
pitch = diag / 200.0
|
||||||
|
vg = m.voxelized(pitch=float(pitch)).fill()
|
||||||
|
out = vg.marching_cubes
|
||||||
|
out.merge_vertices()
|
||||||
|
trimesh.repair.fix_normals(out)
|
||||||
|
else: # repair
|
||||||
|
out = mesh.copy()
|
||||||
|
out.merge_vertices()
|
||||||
|
trimesh.repair.fix_winding(out)
|
||||||
|
trimesh.repair.fill_holes(out)
|
||||||
|
trimesh.repair.fix_normals(out)
|
||||||
|
|
||||||
|
parent = os.path.dirname(out_path)
|
||||||
|
if parent:
|
||||||
|
os.makedirs(parent, exist_ok=True)
|
||||||
|
out.export(out_path)
|
||||||
|
except ImportError as exc:
|
||||||
|
return {**base_err, "was_watertight": was,
|
||||||
|
"error": f"falta dependencia para method='{method}': {exc}. "
|
||||||
|
f"El voxel-remesh necesita scikit-image: cd python && uv add scikit-image"}
|
||||||
|
except Exception as exc:
|
||||||
|
return {**base_err, "was_watertight": was,
|
||||||
|
"error": f"fallo en method='{method}': {type(exc).__name__}: {exc}"}
|
||||||
|
|
||||||
|
return {
|
||||||
|
"ok": True,
|
||||||
|
"was_watertight": was,
|
||||||
|
"is_watertight": bool(out.is_watertight),
|
||||||
|
"out_path": out_path,
|
||||||
|
"method": method,
|
||||||
|
"pitch": round(float(pitch), 6) if pitch is not None else None,
|
||||||
|
"out_faces": int(len(out.faces)),
|
||||||
|
"error": "",
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
import json
|
||||||
|
import sys
|
||||||
|
|
||||||
|
src = sys.argv[1] if len(sys.argv) > 1 else (
|
||||||
|
os.path.expanduser("~/ComfyUI/output/3d_robot_mesh_00001__dec80k.glb"))
|
||||||
|
method = sys.argv[2] if len(sys.argv) > 2 else "voxel"
|
||||||
|
out = sys.argv[3] if len(sys.argv) > 3 else None
|
||||||
|
print(json.dumps(comfyui_make_watertight(src, method=method, out_path=out), indent=2))
|
||||||
@@ -0,0 +1,82 @@
|
|||||||
|
---
|
||||||
|
name: comfyui_simplify_mesh
|
||||||
|
kind: function
|
||||||
|
lang: py
|
||||||
|
domain: ml
|
||||||
|
version: "1.0.0"
|
||||||
|
purity: impure
|
||||||
|
signature: "def comfyui_simplify_mesh(in_path: str, *, target_faces: int = 80000, weld: bool = True, out_path: str | None = None) -> dict"
|
||||||
|
description: "Decima (simplifica) una malla 3D GLB/OBJ/PLY a target_faces conservando su apariencia. Post-proceso de las mallas densas de Hunyuan3D/ComfyUI (60 MB / ~1.67 M caras). Suelda los vertices duplicados ANTES del quadric edge collapse (pymeshlab) — las mallas cube-soup de VoxelToMeshBasic no decimar sin soldar primero. Conserva vertex colors (ColorVisuals, los interpola pymeshlab a traves del collapse) o textura+UV (TextureVisuals, reproyecta UV por vertice mas cercano con scipy y readjunta la imagen). Impura: lee y escribe en disco con trimesh + pymeshlab + scipy."
|
||||||
|
tags: [comfyui, 3d, mesh, hunyuan3d, decimation, simplify, pymeshlab, trimesh, ml]
|
||||||
|
uses_functions: []
|
||||||
|
uses_types: []
|
||||||
|
returns: []
|
||||||
|
returns_optional: false
|
||||||
|
error_type: error_go_core
|
||||||
|
imports: []
|
||||||
|
params:
|
||||||
|
- name: in_path
|
||||||
|
desc: "Ruta de la malla de entrada (.glb/.obj/.ply/.gltf/.stl/.off). Si es un GLB Scene con varias geometrias, se concatenan en una sola malla."
|
||||||
|
- name: target_faces
|
||||||
|
desc: "Numero de caras objetivo tras la decimacion. Si es >= a las caras soldadas, no decima (decimate_status lo indica). keyword-only. Default 80000."
|
||||||
|
- name: weld
|
||||||
|
desc: "Si True (default), suelda vertices duplicados (meshing_remove_duplicate_vertices) antes del collapse. CLAVE para las mallas cube-soup de VoxelToMeshBasic: sin el, el quadric edge collapse devuelve las caras intactas. keyword-only."
|
||||||
|
- name: out_path
|
||||||
|
desc: "Ruta de salida. Si None, escribe '<in>_simplified.glb' junto al original (NO sobrescribe el original). keyword-only."
|
||||||
|
output: "dict {ok, in_faces, out_faces, in_mb, out_mb, out_path, welded_faces, decimate_status, appearance, error}. in/out_faces = caras antes/despues; in/out_mb = tamano de archivo en MB; welded_faces = caras tras soldar; decimate_status = 'ok' o 'skipped_target_ge_welded(N)'; appearance = 'vertex_color'|'texture'|'none'. Si falla, ok=False y error explica (dependencia ausente, archivo no existe, carga o export)."
|
||||||
|
tested: false
|
||||||
|
tests: []
|
||||||
|
test_file_path: ""
|
||||||
|
file_path: "python/functions/ml/comfyui_simplify_mesh.py"
|
||||||
|
---
|
||||||
|
|
||||||
|
## Ejemplo
|
||||||
|
|
||||||
|
```python
|
||||||
|
import sys, os
|
||||||
|
sys.path.insert(0, os.path.join(os.environ["HOME"], "fn_registry", "python", "functions"))
|
||||||
|
from ml.comfyui_simplify_mesh import comfyui_simplify_mesh
|
||||||
|
|
||||||
|
# Decima la malla densa de un personaje (964k caras, 34.7 MB) a 80k caras,
|
||||||
|
# conservando los vertex colors. No toca el original.
|
||||||
|
res = comfyui_simplify_mesh(
|
||||||
|
os.path.expanduser("~/ComfyUI/output/character_3d_00001_.glb"),
|
||||||
|
target_faces=80000,
|
||||||
|
out_path="/tmp/character_simplified.glb",
|
||||||
|
)
|
||||||
|
# res == {"ok": True, "in_faces": 964332, "out_faces": 80000,
|
||||||
|
# "in_mb": 34.718, "out_mb": 1.429, "appearance": "vertex_color",
|
||||||
|
# "decimate_status": "ok", "out_path": "/tmp/character_simplified.glb", ...}
|
||||||
|
```
|
||||||
|
|
||||||
|
Lanzar con el python del venv del registry (import de arriba o heredoc). `./fn run`
|
||||||
|
directo no aplica: la firma usa `*` (keyword-only), no soportado por el runner de `fn run`.
|
||||||
|
|
||||||
|
## Cuando usarla
|
||||||
|
|
||||||
|
Cuando una malla 3D de ComfyUI/Hunyuan3D sale demasiado densa (decenas de MB,
|
||||||
|
millones de caras) y necesitas una version ligera para visor web, repo, deploy o
|
||||||
|
texturizado posterior. Es el post-proceso de los .glb que baja
|
||||||
|
`comfyui_fetch_output_mesh`. Para hacerla ademas estanca, encadena con
|
||||||
|
`comfyui_make_watertight`. Si la malla ya es ligera (caras <= target_faces) no hace
|
||||||
|
nada destructivo: el campo `decimate_status` lo refleja.
|
||||||
|
|
||||||
|
## Gotchas
|
||||||
|
|
||||||
|
- Impura: lee `in_path` y escribe `out_path` en disco. Nunca sobrescribe el
|
||||||
|
original salvo que pases `out_path` apuntando a el.
|
||||||
|
- `weld=True` es imprescindible para las mallas cube-soup de `VoxelToMeshBasic`
|
||||||
|
(4 vertices por cara sin compartir aristas). Con `weld=False` sobre una cube-soup
|
||||||
|
el quadric edge collapse no reduce caras. Solo pon `weld=False` si sabes que la
|
||||||
|
malla ya tiene topologia soldada y quieres preservarla exacta.
|
||||||
|
- Vertex colors: pymeshlab los interpola a traves del collapse y se readjuntan
|
||||||
|
fielmente (verificado). Textura+UV: la reproyeccion de UV es por vertice mas
|
||||||
|
cercano (scipy cKDTree), aproximada — fiel para mallas densas, puede mostrar
|
||||||
|
ligero corrimiento en bordes de isla UV; la imagen de textura se readjunta sin
|
||||||
|
recortar. La via de raiz para malla texturizada estanca es generar con
|
||||||
|
`VoxelToMesh algorithm='surface net'` (ver report 0088), no este post-proceso.
|
||||||
|
- El voxel-remesh de `comfyui_make_watertight` descarta la apariencia; si quieres
|
||||||
|
malla ligera Y con color, decima con esta funcion y NO la pases por watertight
|
||||||
|
voxel (o reproyecta el color despues).
|
||||||
|
- Requiere trimesh + pymeshlab + scipy en el venv del registry (`cd python && uv
|
||||||
|
add trimesh pymeshlab scipy`). Sin ellas devuelve ok=False con el detalle.
|
||||||
@@ -0,0 +1,171 @@
|
|||||||
|
"""Decima (simplifica) una malla 3D GLB/OBJ/PLY conservando su apariencia.
|
||||||
|
|
||||||
|
Post-proceso de las mallas densas que produce el pipeline Hunyuan3D de ComfyUI
|
||||||
|
(60 MB / ~1.67 M caras). Suelda los vertices duplicados ANTES del collapse —
|
||||||
|
las mallas de VoxelToMeshBasic son "cube-soup" (4 vertices nuevos por cara, sin
|
||||||
|
compartir aristas) y el quadric edge collapse no las decima si no se sueldan
|
||||||
|
primero. Luego aplica meshing_decimation_quadric_edge_collapse (pymeshlab), el
|
||||||
|
mismo filtro que el FaceReducer del wrapper Hy3D usa internamente.
|
||||||
|
|
||||||
|
Conserva la apariencia segun el tipo del original:
|
||||||
|
- Vertex colors (ColorVisuals, lo habitual en el shape stage de Hunyuan3D):
|
||||||
|
pymeshlab los interpola a traves del collapse y se vuelven a adjuntar.
|
||||||
|
- Textura (TextureVisuals con UV + baseColorTexture): reproyecta las UV por
|
||||||
|
vertice mas cercano (scipy cKDTree, sin rtree) y readjunta la imagen.
|
||||||
|
- Sin apariencia: simplifica la geometria igual.
|
||||||
|
|
||||||
|
Impura: lee y escribe archivos en disco. Requiere trimesh + pymeshlab + scipy.
|
||||||
|
"""
|
||||||
|
import os
|
||||||
|
|
||||||
|
import numpy as np
|
||||||
|
|
||||||
|
|
||||||
|
def _err(in_faces, in_mb, msg):
|
||||||
|
return {
|
||||||
|
"ok": False, "in_faces": in_faces, "out_faces": 0,
|
||||||
|
"in_mb": in_mb, "out_mb": 0.0, "out_path": "",
|
||||||
|
"welded_faces": 0, "decimate_status": "", "appearance": "",
|
||||||
|
"error": msg,
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
def _load_mesh(path):
|
||||||
|
import trimesh
|
||||||
|
|
||||||
|
obj = trimesh.load(path, process=False)
|
||||||
|
if isinstance(obj, trimesh.Scene):
|
||||||
|
obj = trimesh.util.concatenate(list(obj.geometry.values()))
|
||||||
|
return obj
|
||||||
|
|
||||||
|
|
||||||
|
def _detect_appearance(mesh):
|
||||||
|
"""Devuelve (kind, attr, image): 'vertex_color'|'texture'|'none'."""
|
||||||
|
import trimesh
|
||||||
|
|
||||||
|
vis = mesh.visual
|
||||||
|
if isinstance(vis, trimesh.visual.texture.TextureVisuals) and vis.uv is not None:
|
||||||
|
img = getattr(getattr(vis, "material", None), "baseColorTexture", None)
|
||||||
|
if img is not None:
|
||||||
|
return "texture", np.asarray(vis.uv, dtype=np.float64), img
|
||||||
|
if isinstance(vis, trimesh.visual.color.ColorVisuals):
|
||||||
|
vc = vis.vertex_colors
|
||||||
|
if vc is not None and len(vc) == len(mesh.vertices):
|
||||||
|
return "vertex_color", np.asarray(vc, dtype=np.uint8), None
|
||||||
|
return "none", None, None
|
||||||
|
|
||||||
|
|
||||||
|
def comfyui_simplify_mesh(
|
||||||
|
in_path: str,
|
||||||
|
*,
|
||||||
|
target_faces: int = 80000,
|
||||||
|
weld: bool = True,
|
||||||
|
out_path: str | None = None,
|
||||||
|
) -> dict:
|
||||||
|
"""Decima una malla GLB/OBJ/PLY a target_faces conservando su apariencia.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
in_path: ruta de la malla de entrada (.glb/.obj/.ply/.gltf/.stl/.off).
|
||||||
|
target_faces: numero de caras objetivo tras la decimacion. keyword-only.
|
||||||
|
weld: si True (default), suelda vertices duplicados antes del collapse.
|
||||||
|
Imprescindible para las mallas cube-soup de VoxelToMeshBasic; sin el,
|
||||||
|
el collapse no reduce caras. keyword-only.
|
||||||
|
out_path: ruta de salida. Si None, escribe "<in>_simplified.glb" junto al
|
||||||
|
original. keyword-only.
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
dict {ok, in_faces, out_faces, in_mb, out_mb, out_path, welded_faces,
|
||||||
|
decimate_status, appearance, error}. Si falla, ok=False y error explica.
|
||||||
|
"""
|
||||||
|
try:
|
||||||
|
import pymeshlab as ml
|
||||||
|
import trimesh
|
||||||
|
except ImportError as exc:
|
||||||
|
return _err(0, 0.0, f"falta dependencia: {exc}. Instala en el venv del "
|
||||||
|
f"registry: cd python && uv add trimesh pymeshlab scipy")
|
||||||
|
|
||||||
|
if not os.path.exists(in_path):
|
||||||
|
return _err(0, 0.0, f"no existe el archivo de entrada: {in_path!r}")
|
||||||
|
if out_path is None:
|
||||||
|
out_path = os.path.splitext(in_path)[0] + "_simplified.glb"
|
||||||
|
|
||||||
|
in_mb = round(os.path.getsize(in_path) / 1e6, 3)
|
||||||
|
try:
|
||||||
|
orig = _load_mesh(in_path)
|
||||||
|
except Exception as exc:
|
||||||
|
return _err(0, in_mb, f"no se pudo cargar la malla {in_path!r}: {exc}")
|
||||||
|
|
||||||
|
in_faces = int(len(orig.faces))
|
||||||
|
kind, attr, image = _detect_appearance(orig)
|
||||||
|
|
||||||
|
try:
|
||||||
|
ms = ml.MeshSet()
|
||||||
|
if kind == "vertex_color":
|
||||||
|
ms.add_mesh(ml.Mesh(
|
||||||
|
vertex_matrix=orig.vertices, face_matrix=orig.faces,
|
||||||
|
v_color_matrix=attr.astype(np.float64) / 255.0,
|
||||||
|
))
|
||||||
|
else:
|
||||||
|
ms.add_mesh(ml.Mesh(vertex_matrix=orig.vertices, face_matrix=orig.faces))
|
||||||
|
|
||||||
|
if weld:
|
||||||
|
ms.apply_filter("meshing_remove_duplicate_vertices")
|
||||||
|
ms.apply_filter("meshing_remove_unreferenced_vertices")
|
||||||
|
welded_faces = int(ms.current_mesh().face_number())
|
||||||
|
|
||||||
|
decimate_status = "ok"
|
||||||
|
if target_faces < welded_faces:
|
||||||
|
ms.apply_filter(
|
||||||
|
"meshing_decimation_quadric_edge_collapse",
|
||||||
|
targetfacenum=int(target_faces), qualitythr=0.3,
|
||||||
|
preserveboundary=True, boundaryweight=3.0,
|
||||||
|
preservenormal=True, preservetopology=True, autoclean=True,
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
decimate_status = f"skipped_target_ge_welded({welded_faces})"
|
||||||
|
|
||||||
|
cm = ms.current_mesh()
|
||||||
|
dec = trimesh.Trimesh(
|
||||||
|
vertices=cm.vertex_matrix(), faces=cm.face_matrix(), process=False,
|
||||||
|
)
|
||||||
|
|
||||||
|
appearance = kind
|
||||||
|
if kind == "vertex_color" and cm.has_vertex_color():
|
||||||
|
cols = np.clip(cm.vertex_color_matrix() * 255.0, 0, 255).astype(np.uint8)
|
||||||
|
dec.visual = trimesh.visual.color.ColorVisuals(mesh=dec, vertex_colors=cols)
|
||||||
|
elif kind == "texture":
|
||||||
|
from scipy.spatial import cKDTree
|
||||||
|
|
||||||
|
_, idx = cKDTree(orig.vertices).query(dec.vertices)
|
||||||
|
dec.visual = trimesh.visual.texture.TextureVisuals(uv=attr[idx], image=image)
|
||||||
|
|
||||||
|
parent = os.path.dirname(out_path)
|
||||||
|
if parent:
|
||||||
|
os.makedirs(parent, exist_ok=True)
|
||||||
|
dec.export(out_path)
|
||||||
|
except Exception as exc:
|
||||||
|
return _err(in_faces, in_mb, f"fallo al decimar/exportar: {type(exc).__name__}: {exc}")
|
||||||
|
|
||||||
|
return {
|
||||||
|
"ok": True,
|
||||||
|
"in_faces": in_faces,
|
||||||
|
"out_faces": int(len(dec.faces)),
|
||||||
|
"in_mb": in_mb,
|
||||||
|
"out_mb": round(os.path.getsize(out_path) / 1e6, 3),
|
||||||
|
"out_path": out_path,
|
||||||
|
"welded_faces": welded_faces,
|
||||||
|
"decimate_status": decimate_status,
|
||||||
|
"appearance": appearance,
|
||||||
|
"error": "",
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
import json
|
||||||
|
import sys
|
||||||
|
|
||||||
|
src = sys.argv[1] if len(sys.argv) > 1 else (
|
||||||
|
os.path.expanduser("~/ComfyUI/output/character_3d_00001_.glb"))
|
||||||
|
tgt = int(sys.argv[2]) if len(sys.argv) > 2 else 80000
|
||||||
|
out = sys.argv[3] if len(sys.argv) > 3 else None
|
||||||
|
print(json.dumps(comfyui_simplify_mesh(src, target_faces=tgt, out_path=out), indent=2))
|
||||||
@@ -21,6 +21,7 @@ dependencies = [
|
|||||||
"matplotlib>=3.10.9",
|
"matplotlib>=3.10.9",
|
||||||
"openpyxl>=3.1.5",
|
"openpyxl>=3.1.5",
|
||||||
"polars>=1.40.1",
|
"polars>=1.40.1",
|
||||||
|
"pymeshlab>=2025.7.post1",
|
||||||
"pymssql>=2.3.13",
|
"pymssql>=2.3.13",
|
||||||
"pypdf>=6.10.0",
|
"pypdf>=6.10.0",
|
||||||
"pyproj>=3.7.2",
|
"pyproj>=3.7.2",
|
||||||
@@ -28,10 +29,12 @@ dependencies = [
|
|||||||
"pyyaml>=6.0.3",
|
"pyyaml>=6.0.3",
|
||||||
"rapidfuzz>=3.14.5",
|
"rapidfuzz>=3.14.5",
|
||||||
"reportlab>=4.5.0",
|
"reportlab>=4.5.0",
|
||||||
|
"scikit-image>=0.26.0",
|
||||||
"scikit-learn>=1.8.0",
|
"scikit-learn>=1.8.0",
|
||||||
"scipy>=1.17.1",
|
"scipy>=1.17.1",
|
||||||
"seaborn>=0.13.2",
|
"seaborn>=0.13.2",
|
||||||
"shapely>=2.1.2",
|
"shapely>=2.1.2",
|
||||||
|
"trimesh>=4.12.2",
|
||||||
"xlrd>=2.0.2",
|
"xlrd>=2.0.2",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|||||||
Generated
+138
@@ -902,6 +902,7 @@ dependencies = [
|
|||||||
{ name = "matplotlib" },
|
{ name = "matplotlib" },
|
||||||
{ name = "openpyxl" },
|
{ name = "openpyxl" },
|
||||||
{ name = "polars" },
|
{ name = "polars" },
|
||||||
|
{ name = "pymeshlab" },
|
||||||
{ name = "pymssql" },
|
{ name = "pymssql" },
|
||||||
{ name = "pypdf" },
|
{ name = "pypdf" },
|
||||||
{ name = "pyproj" },
|
{ name = "pyproj" },
|
||||||
@@ -909,10 +910,12 @@ dependencies = [
|
|||||||
{ name = "pyyaml" },
|
{ name = "pyyaml" },
|
||||||
{ name = "rapidfuzz" },
|
{ name = "rapidfuzz" },
|
||||||
{ name = "reportlab" },
|
{ name = "reportlab" },
|
||||||
|
{ name = "scikit-image" },
|
||||||
{ name = "scikit-learn" },
|
{ name = "scikit-learn" },
|
||||||
{ name = "scipy" },
|
{ name = "scipy" },
|
||||||
{ name = "seaborn" },
|
{ name = "seaborn" },
|
||||||
{ name = "shapely" },
|
{ name = "shapely" },
|
||||||
|
{ name = "trimesh" },
|
||||||
{ name = "xlrd" },
|
{ name = "xlrd" },
|
||||||
]
|
]
|
||||||
|
|
||||||
@@ -955,6 +958,7 @@ requires-dist = [
|
|||||||
{ name = "matplotlib", specifier = ">=3.10.9" },
|
{ name = "matplotlib", specifier = ">=3.10.9" },
|
||||||
{ name = "openpyxl", specifier = ">=3.1.5" },
|
{ name = "openpyxl", specifier = ">=3.1.5" },
|
||||||
{ name = "polars", specifier = ">=1.40.1" },
|
{ name = "polars", specifier = ">=1.40.1" },
|
||||||
|
{ name = "pymeshlab", specifier = ">=2025.7.post1" },
|
||||||
{ name = "pymssql", specifier = ">=2.3.13" },
|
{ name = "pymssql", specifier = ">=2.3.13" },
|
||||||
{ name = "pypdf", specifier = ">=6.10.0" },
|
{ name = "pypdf", specifier = ">=6.10.0" },
|
||||||
{ name = "pyproj", specifier = ">=3.7.2" },
|
{ name = "pyproj", specifier = ">=3.7.2" },
|
||||||
@@ -962,10 +966,12 @@ requires-dist = [
|
|||||||
{ name = "pyyaml", specifier = ">=6.0.3" },
|
{ name = "pyyaml", specifier = ">=6.0.3" },
|
||||||
{ name = "rapidfuzz", specifier = ">=3.14.5" },
|
{ name = "rapidfuzz", specifier = ">=3.14.5" },
|
||||||
{ name = "reportlab", specifier = ">=4.5.0" },
|
{ name = "reportlab", specifier = ">=4.5.0" },
|
||||||
|
{ name = "scikit-image", specifier = ">=0.26.0" },
|
||||||
{ name = "scikit-learn", specifier = ">=1.8.0" },
|
{ name = "scikit-learn", specifier = ">=1.8.0" },
|
||||||
{ name = "scipy", specifier = ">=1.17.1" },
|
{ name = "scipy", specifier = ">=1.17.1" },
|
||||||
{ name = "seaborn", specifier = ">=0.13.2" },
|
{ name = "seaborn", specifier = ">=0.13.2" },
|
||||||
{ name = "shapely", specifier = ">=2.1.2" },
|
{ name = "shapely", specifier = ">=2.1.2" },
|
||||||
|
{ name = "trimesh", specifier = ">=4.12.2" },
|
||||||
{ name = "xlrd", specifier = ">=2.0.2" },
|
{ name = "xlrd", specifier = ">=2.0.2" },
|
||||||
]
|
]
|
||||||
provides-extras = ["nlp", "jupyter"]
|
provides-extras = ["nlp", "jupyter"]
|
||||||
@@ -1577,6 +1583,19 @@ wheels = [
|
|||||||
{ url = "https://files.pythonhosted.org/packages/0e/61/66938bbb5fc52dbdf84594873d5b51fb1f7c7794e9c0f5bd885f30bc507b/idna-3.11-py3-none-any.whl", hash = "sha256:771a87f49d9defaf64091e6e6fe9c18d4833f140bd19464795bc32d966ca37ea", size = 71008, upload-time = "2025-10-12T14:55:18.883Z" },
|
{ url = "https://files.pythonhosted.org/packages/0e/61/66938bbb5fc52dbdf84594873d5b51fb1f7c7794e9c0f5bd885f30bc507b/idna-3.11-py3-none-any.whl", hash = "sha256:771a87f49d9defaf64091e6e6fe9c18d4833f140bd19464795bc32d966ca37ea", size = 71008, upload-time = "2025-10-12T14:55:18.883Z" },
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "imageio"
|
||||||
|
version = "2.37.3"
|
||||||
|
source = { registry = "https://pypi.org/simple" }
|
||||||
|
dependencies = [
|
||||||
|
{ name = "numpy" },
|
||||||
|
{ name = "pillow" },
|
||||||
|
]
|
||||||
|
sdist = { url = "https://files.pythonhosted.org/packages/b1/84/93bcd1300216ea50811cee96873b84a1bebf8d0489ffaf7f2a3756bab866/imageio-2.37.3.tar.gz", hash = "sha256:bbb37efbfc4c400fcd534b367b91fcd66d5da639aaa138034431a1c5e0a41451", size = 389673, upload-time = "2026-03-09T11:31:12.573Z" }
|
||||||
|
wheels = [
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/49/fa/391e437a34e55095173dca5f24070d89cbc233ff85bf1c29c93248c6588d/imageio-2.37.3-py3-none-any.whl", hash = "sha256:46f5bb8522cd421c0f5ae104d8268f569d856b29eb1a13b92829d1970f32c9f0", size = 317646, upload-time = "2026-03-09T11:31:10.771Z" },
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "iniconfig"
|
name = "iniconfig"
|
||||||
version = "2.3.0"
|
version = "2.3.0"
|
||||||
@@ -2180,6 +2199,18 @@ wheels = [
|
|||||||
{ url = "https://files.pythonhosted.org/packages/82/3d/14ce75ef66813643812f3093ab17e46d3a206942ce7376d31ec2d36229e7/lark-1.3.1-py3-none-any.whl", hash = "sha256:c629b661023a014c37da873b4ff58a817398d12635d3bbb2c5a03be7fe5d1e12", size = 113151, upload-time = "2025-10-27T18:25:54.882Z" },
|
{ url = "https://files.pythonhosted.org/packages/82/3d/14ce75ef66813643812f3093ab17e46d3a206942ce7376d31ec2d36229e7/lark-1.3.1-py3-none-any.whl", hash = "sha256:c629b661023a014c37da873b4ff58a817398d12635d3bbb2c5a03be7fe5d1e12", size = 113151, upload-time = "2025-10-27T18:25:54.882Z" },
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "lazy-loader"
|
||||||
|
version = "0.5"
|
||||||
|
source = { registry = "https://pypi.org/simple" }
|
||||||
|
dependencies = [
|
||||||
|
{ name = "packaging" },
|
||||||
|
]
|
||||||
|
sdist = { url = "https://files.pythonhosted.org/packages/49/ac/21a1f8aa3777f5658576777ea76bfb124b702c520bbe90edf4ae9915eafa/lazy_loader-0.5.tar.gz", hash = "sha256:717f9179a0dbed357012ddad50a5ad3d5e4d9a0b8712680d4e687f5e6e6ed9b3", size = 15294, upload-time = "2026-03-06T15:45:09.054Z" }
|
||||||
|
wheels = [
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/8a/a1/8d812e53a5da1687abb10445275d41a8b13adb781bbf7196ddbcf8d88505/lazy_loader-0.5-py3-none-any.whl", hash = "sha256:ab0ea149e9c554d4ffeeb21105ac60bed7f3b4fd69b1d2360a4add51b170b005", size = 8044, upload-time = "2026-03-06T15:45:07.668Z" },
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "lxml"
|
name = "lxml"
|
||||||
version = "6.0.2"
|
version = "6.0.2"
|
||||||
@@ -3627,6 +3658,31 @@ crypto = [
|
|||||||
{ name = "cryptography" },
|
{ name = "cryptography" },
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "pymeshlab"
|
||||||
|
version = "2025.7.post1"
|
||||||
|
source = { registry = "https://pypi.org/simple" }
|
||||||
|
dependencies = [
|
||||||
|
{ name = "numpy" },
|
||||||
|
]
|
||||||
|
wheels = [
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/ae/c1/a8db8ba66b5c51e700ba0eccea2c81f68a3223b775b0afe7b30a3da9a2ec/pymeshlab-2025.7.post1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:693101c1ade7aadbad114878626307bf434fe607de873449fbe6b6b95a30cd01", size = 64995577, upload-time = "2026-01-30T08:40:55.627Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/f8/0d/6692ef6d96fa27763899665562c11ee6411eba55b2bddcda6799213dadac/pymeshlab-2025.7.post1-cp312-cp312-macosx_11_0_x86_64.whl", hash = "sha256:265503a06968420c8eb6934e3db78ff0767518000d8afd46ef3c976a506cfcf7", size = 54506925, upload-time = "2026-01-30T08:40:58.707Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/6b/8d/6082aa85f8c918901221d1a7e1e810cb5b56eecbed59a5e688feea92c148/pymeshlab-2025.7.post1-cp312-cp312-manylinux_2_35_aarch64.whl", hash = "sha256:d39fbaac1274adbbdf75cd999710d2ba48bd4d9087f34815afbdedb99dd3ded6", size = 65341068, upload-time = "2026-01-30T08:41:02.003Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/a3/4c/b0b1b5ad425acd80abcff4632f0241ca490c52ef9c48013d71f573680a2a/pymeshlab-2025.7.post1-cp312-cp312-manylinux_2_35_x86_64.whl", hash = "sha256:bc453d89b114671affc747991a939b257d2320b71885b31213190c64081f5c35", size = 106530409, upload-time = "2026-01-30T08:41:05.155Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/4f/06/66b91d2d77fbb2bf729dfe58692957bad3cea706ecb3fe51fca4b07c0c95/pymeshlab-2025.7.post1-cp312-cp312-win_amd64.whl", hash = "sha256:fc04cb2206e8d0194b2c8f61ea6ef54505bbe3d217e7f1960ee9608464f9bfad", size = 55211790, upload-time = "2026-01-30T08:41:08.339Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/a7/06/ef68bf08d23f44118ab846b93dd30eaf87ad85cc44b4f3e5ac8764e9bc9f/pymeshlab-2025.7.post1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:841b1fa15fc76ab73e594f4bbfcbe339782b36be67d9387ff5aa5f4ca422e180", size = 64995970, upload-time = "2026-01-30T08:41:11.153Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/27/52/a11aa52eb3b250f78a891b9e4ffcdf4af4da13a462d079cc6cf3d17d34ac/pymeshlab-2025.7.post1-cp313-cp313-macosx_11_0_x86_64.whl", hash = "sha256:06c7171f70ff86753535d1c0d952ead34854923061af37197e9cc22dea515e9d", size = 54507011, upload-time = "2026-01-30T08:41:14.507Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/0a/4e/31b08dddba8c77676c9cf7ed90810b7dfcbd99cba845bb9b20b7bbaa4d7c/pymeshlab-2025.7.post1-cp313-cp313-manylinux_2_35_aarch64.whl", hash = "sha256:2432dffe99e58e1b5e77dbfeb7690502b6d0ebccb1ed75356fca4676ec56c9a2", size = 65242911, upload-time = "2026-01-30T08:41:17.622Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/7f/af/3f7597d43813e8918bc2798aeed9b3be123a62e8a5be7de032cce03db8ed/pymeshlab-2025.7.post1-cp313-cp313-manylinux_2_35_x86_64.whl", hash = "sha256:99bb0f83ad20c61bdc63beb8d7f0c9ed3af6912a4770da170ce8d4bd02a7ecb0", size = 106407568, upload-time = "2026-01-30T08:41:25.759Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/a2/69/1732c3222ce63758c32746841099ac82059907cc3ff6bd77499da78abcbc/pymeshlab-2025.7.post1-cp313-cp313-win_amd64.whl", hash = "sha256:25eb2578dd6c4d1b2e0253fb3b4f8f7895e8bb4f3f1236832db0ab58e6a44998", size = 55211755, upload-time = "2026-01-30T08:41:29.593Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/29/e6/68bb19ec11de2f60bc3319e0ce93aba4082ec82a6bbc03dd142f0d319585/pymeshlab-2025.7.post1-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:c9990cd5e4620fc598795baf91f1b7b37ebb65a7b87eb01beb54d37339207d46", size = 64996542, upload-time = "2026-01-30T08:41:33.604Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/65/0d/58258e56400f3a5ff9df565b4ff48616568af25aa5d8a70eb2afee467709/pymeshlab-2025.7.post1-cp314-cp314-macosx_11_0_x86_64.whl", hash = "sha256:472b7247e4ae9b9937d9a13bfb78b9e6e777b805ae20a114101f9dcc15bea8fc", size = 54507346, upload-time = "2026-01-30T08:41:36.517Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/ac/01/b26a8c0d70a76fc333a620ce1ee7b11f8ab4b3791306350e28a578dcb47f/pymeshlab-2025.7.post1-cp314-cp314-manylinux_2_35_aarch64.whl", hash = "sha256:de6468bf43d5eeb23cdac78fe30286694ff5ad6d349a9bfa44584ac7e434e054", size = 65417867, upload-time = "2026-01-30T08:41:39.434Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/79/c0/9b769a1acd7ce4405059820793c2f14129d9faba99b595ea35c8c9d8c57d/pymeshlab-2025.7.post1-cp314-cp314-manylinux_2_35_x86_64.whl", hash = "sha256:951fe5aeb3e92632f3db3a1a6525279b41e5d7191c6b9011429dbb0b67f2f0d3", size = 106572030, upload-time = "2026-01-30T08:41:43.909Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/3e/f0/65e3b96a14e9c80e05c085f8b32b923ccd5a70acf63eb66528e3fa94cf54/pymeshlab-2025.7.post1-cp314-cp314-win_amd64.whl", hash = "sha256:881389fb62ac832c81555fe22a3990a81624deb78e78ca3862836075d5c62c2b", size = 56595688, upload-time = "2026-01-30T08:41:47.145Z" },
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "pymssql"
|
name = "pymssql"
|
||||||
version = "2.3.13"
|
version = "2.3.13"
|
||||||
@@ -4382,6 +4438,64 @@ wheels = [
|
|||||||
{ url = "https://files.pythonhosted.org/packages/5d/e6/ec8471c8072382cb91233ba7267fd931219753bb43814cbc71757bfd4dab/safetensors-0.7.0-cp38-abi3-win_amd64.whl", hash = "sha256:d1239932053f56f3456f32eb9625590cc7582e905021f94636202a864d470755", size = 341380, upload-time = "2025-11-19T15:18:44.427Z" },
|
{ url = "https://files.pythonhosted.org/packages/5d/e6/ec8471c8072382cb91233ba7267fd931219753bb43814cbc71757bfd4dab/safetensors-0.7.0-cp38-abi3-win_amd64.whl", hash = "sha256:d1239932053f56f3456f32eb9625590cc7582e905021f94636202a864d470755", size = 341380, upload-time = "2025-11-19T15:18:44.427Z" },
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "scikit-image"
|
||||||
|
version = "0.26.0"
|
||||||
|
source = { registry = "https://pypi.org/simple" }
|
||||||
|
dependencies = [
|
||||||
|
{ name = "imageio" },
|
||||||
|
{ name = "lazy-loader" },
|
||||||
|
{ name = "networkx" },
|
||||||
|
{ name = "numpy" },
|
||||||
|
{ name = "packaging" },
|
||||||
|
{ name = "pillow" },
|
||||||
|
{ name = "scipy" },
|
||||||
|
{ name = "tifffile" },
|
||||||
|
]
|
||||||
|
sdist = { url = "https://files.pythonhosted.org/packages/a1/b4/2528bb43c67d48053a7a649a9666432dc307d66ba02e3a6d5c40f46655df/scikit_image-0.26.0.tar.gz", hash = "sha256:f5f970ab04efad85c24714321fcc91613fcb64ef2a892a13167df2f3e59199fa", size = 22729739, upload-time = "2025-12-20T17:12:21.824Z" }
|
||||||
|
wheels = [
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/99/e8/e13757982264b33a1621628f86b587e9a73a13f5256dad49b19ba7dc9083/scikit_image-0.26.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:d454b93a6fa770ac5ae2d33570f8e7a321bb80d29511ce4b6b78058ebe176e8c", size = 12376452, upload-time = "2025-12-20T17:10:52.796Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/e3/be/f8dd17d0510f9911f9f17ba301f7455328bf13dae416560126d428de9568/scikit_image-0.26.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:3409e89d66eff5734cd2b672d1c48d2759360057e714e1d92a11df82c87cba37", size = 12061567, upload-time = "2025-12-20T17:10:55.207Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/b3/2b/c70120a6880579fb42b91567ad79feb4772f7be72e8d52fec403a3dde0c6/scikit_image-0.26.0-cp312-cp312-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:4c717490cec9e276afb0438dd165b7c3072d6c416709cc0f9f5a4c1070d23a44", size = 13084214, upload-time = "2025-12-20T17:10:57.468Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/f4/a2/70401a107d6d7466d64b466927e6b96fcefa99d57494b972608e2f8be50f/scikit_image-0.26.0-cp312-cp312-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:7df650e79031634ac90b11e64a9eedaf5a5e06fcd09bcd03a34be01745744466", size = 13561683, upload-time = "2025-12-20T17:10:59.49Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/13/a5/48bdfd92794c5002d664e0910a349d0a1504671ef5ad358150f21643c79a/scikit_image-0.26.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:cefd85033e66d4ea35b525bb0937d7f42d4cdcfed2d1888e1570d5ce450d3932", size = 14112147, upload-time = "2025-12-20T17:11:02.083Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/ee/b5/ac71694da92f5def5953ca99f18a10fe98eac2dd0a34079389b70b4d0394/scikit_image-0.26.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:3f5bf622d7c0435884e1e141ebbe4b2804e16b2dd23ae4c6183e2ea99233be70", size = 14661625, upload-time = "2025-12-20T17:11:04.528Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/23/4d/a3cc1e96f080e253dad2251bfae7587cf2b7912bcd76fd43fd366ff35a87/scikit_image-0.26.0-cp312-cp312-win_amd64.whl", hash = "sha256:abed017474593cd3056ae0fe948d07d0747b27a085e92df5474f4955dd65aec0", size = 11911059, upload-time = "2025-12-20T17:11:06.61Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/35/8a/d1b8055f584acc937478abf4550d122936f420352422a1a625eef2c605d8/scikit_image-0.26.0-cp312-cp312-win_arm64.whl", hash = "sha256:4d57e39ef67a95d26860c8caf9b14b8fb130f83b34c6656a77f191fa6d1d04d8", size = 11348740, upload-time = "2025-12-20T17:11:09.118Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/4f/48/02357ffb2cca35640f33f2cfe054a4d6d5d7a229b88880a64f1e45c11f4e/scikit_image-0.26.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:a2e852eccf41d2d322b8e60144e124802873a92b8d43a6f96331aa42888491c7", size = 12346329, upload-time = "2025-12-20T17:11:11.599Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/67/b9/b792c577cea2c1e94cda83b135a656924fc57c428e8a6d302cd69aac1b60/scikit_image-0.26.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:98329aab3bc87db352b9887f64ce8cdb8e75f7c2daa19927f2e121b797b678d5", size = 12031726, upload-time = "2025-12-20T17:11:13.871Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/07/a9/9564250dfd65cb20404a611016db52afc6268b2b371cd19c7538ea47580f/scikit_image-0.26.0-cp313-cp313-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:915bb3ba66455cf8adac00dc8fdf18a4cd29656aec7ddd38cb4dda90289a6f21", size = 13094910, upload-time = "2025-12-20T17:11:16.2Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/a3/b8/0d8eeb5a9fd7d34ba84f8a55753a0a3e2b5b51b2a5a0ade648a8db4a62f7/scikit_image-0.26.0-cp313-cp313-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:b36ab5e778bf50af5ff386c3ac508027dc3aaeccf2161bdf96bde6848f44d21b", size = 13660939, upload-time = "2025-12-20T17:11:18.464Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/2f/d6/91d8973584d4793d4c1a847d388e34ef1218d835eeddecfc9108d735b467/scikit_image-0.26.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:09bad6a5d5949c7896c8347424c4cca899f1d11668030e5548813ab9c2865dcb", size = 14138938, upload-time = "2025-12-20T17:11:20.919Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/39/9a/7e15d8dc10d6bbf212195fb39bdeb7f226c46dd53f9c63c312e111e2e175/scikit_image-0.26.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:aeb14db1ed09ad4bee4ceb9e635547a8d5f3549be67fc6c768c7f923e027e6cd", size = 14752243, upload-time = "2025-12-20T17:11:23.347Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/8f/58/2b11b933097bc427e42b4a8b15f7de8f24f2bac1fd2779d2aea1431b2c31/scikit_image-0.26.0-cp313-cp313-win_amd64.whl", hash = "sha256:ac529eb9dbd5954f9aaa2e3fe9a3fd9661bfe24e134c688587d811a0233127f1", size = 11906770, upload-time = "2025-12-20T17:11:25.297Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/ad/ec/96941474a18a04b69b6f6562a5bd79bd68049fa3728d3b350976eccb8b93/scikit_image-0.26.0-cp313-cp313-win_arm64.whl", hash = "sha256:a2d211bc355f59725efdcae699b93b30348a19416cc9e017f7b2fb599faf7219", size = 11342506, upload-time = "2025-12-20T17:11:27.399Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/03/e5/c1a9962b0cf1952f42d32b4a2e48eed520320dbc4d2ff0b981c6fa508b6b/scikit_image-0.26.0-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:9eefb4adad066da408a7601c4c24b07af3b472d90e08c3e7483d4e9e829d8c49", size = 12663278, upload-time = "2025-12-20T17:11:29.358Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/ae/97/c1a276a59ce8e4e24482d65c1a3940d69c6b3873279193b7ebd04e5ee56b/scikit_image-0.26.0-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:6caec76e16c970c528d15d1c757363334d5cb3069f9cea93d2bead31820511f3", size = 12405142, upload-time = "2025-12-20T17:11:31.282Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/d4/4a/f1cbd1357caef6c7993f7efd514d6e53d8fd6f7fe01c4714d51614c53289/scikit_image-0.26.0-cp313-cp313t-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:a07200fe09b9d99fcdab959859fe0f7db8df6333d6204344425d476850ce3604", size = 12942086, upload-time = "2025-12-20T17:11:33.683Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/5b/6f/74d9fb87c5655bd64cf00b0c44dc3d6206d9002e5f6ba1c9aeb13236f6bf/scikit_image-0.26.0-cp313-cp313t-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:92242351bccf391fc5df2d1529d15470019496d2498d615beb68da85fe7fdf37", size = 13265667, upload-time = "2025-12-20T17:11:36.11Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/a7/73/faddc2413ae98d863f6fa2e3e14da4467dd38e788e1c23346cf1a2b06b97/scikit_image-0.26.0-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:52c496f75a7e45844d951557f13c08c81487c6a1da2e3c9c8a39fcde958e02cc", size = 14001966, upload-time = "2025-12-20T17:11:38.55Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/02/94/9f46966fa042b5d57c8cd641045372b4e0df0047dd400e77ea9952674110/scikit_image-0.26.0-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:20ef4a155e2e78b8ab973998e04d8a361d49d719e65412405f4dadd9155a61d9", size = 14359526, upload-time = "2025-12-20T17:11:41.087Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/5d/b4/2840fe38f10057f40b1c9f8fb98a187a370936bf144a4ac23452c5ef1baf/scikit_image-0.26.0-cp313-cp313t-win_amd64.whl", hash = "sha256:c9087cf7d0e7f33ab5c46d2068d86d785e70b05400a891f73a13400f1e1faf6a", size = 12287629, upload-time = "2025-12-20T17:11:43.11Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/22/ba/73b6ca70796e71f83ab222690e35a79612f0117e5aaf167151b7d46f5f2c/scikit_image-0.26.0-cp313-cp313t-win_arm64.whl", hash = "sha256:27d58bc8b2acd351f972c6508c1b557cfed80299826080a4d803dd29c51b707e", size = 11647755, upload-time = "2025-12-20T17:11:45.279Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/51/44/6b744f92b37ae2833fd423cce8f806d2368859ec325a699dc30389e090b9/scikit_image-0.26.0-cp314-cp314-macosx_10_15_x86_64.whl", hash = "sha256:63af3d3a26125f796f01052052f86806da5b5e54c6abef152edb752683075a9c", size = 12365810, upload-time = "2025-12-20T17:11:47.357Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/40/f5/83590d9355191f86ac663420fec741b82cc547a4afe7c4c1d986bf46e4db/scikit_image-0.26.0-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:ce00600cd70d4562ed59f80523e18cdcc1fae0e10676498a01f73c255774aefd", size = 12075717, upload-time = "2025-12-20T17:11:49.483Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/72/48/253e7cf5aee6190459fe136c614e2cbccc562deceb4af96e0863f1b8ee29/scikit_image-0.26.0-cp314-cp314-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:6381edf972b32e4f54085449afde64365a57316637496c1325a736987083e2ab", size = 13161520, upload-time = "2025-12-20T17:11:51.58Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/73/c3/cec6a3cbaadfdcc02bd6ff02f3abfe09eaa7f4d4e0a525a1e3a3f4bce49c/scikit_image-0.26.0-cp314-cp314-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:c6624a76c6085218248154cc7e1500e6b488edcd9499004dd0d35040607d7505", size = 13684340, upload-time = "2025-12-20T17:11:53.708Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/d4/0d/39a776f675d24164b3a267aa0db9f677a4cb20127660d8bf4fd7fef66817/scikit_image-0.26.0-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:f775f0e420faac9c2aa6757135f4eb468fb7b70e0b67fa77a5e79be3c30ee331", size = 14203839, upload-time = "2025-12-20T17:11:55.89Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/ee/25/2514df226bbcedfe9b2caafa1ba7bc87231a0c339066981b182b08340e06/scikit_image-0.26.0-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:ede4d6d255cc5da9faeb2f9ba7fedbc990abbc652db429f40a16b22e770bb578", size = 14770021, upload-time = "2025-12-20T17:11:58.014Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/8d/5b/0671dc91c0c79340c3fe202f0549c7d3681eb7640fe34ab68a5f090a7c7f/scikit_image-0.26.0-cp314-cp314-win_amd64.whl", hash = "sha256:0660b83968c15293fd9135e8d860053ee19500d52bf55ca4fb09de595a1af650", size = 12023490, upload-time = "2025-12-20T17:12:00.013Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/65/08/7c4cb59f91721f3de07719085212a0b3962e3e3f2d1818cbac4eeb1ea53e/scikit_image-0.26.0-cp314-cp314-win_arm64.whl", hash = "sha256:b8d14d3181c21c11170477a42542c1addc7072a90b986675a71266ad17abc37f", size = 11473782, upload-time = "2025-12-20T17:12:01.983Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/49/41/65c4258137acef3d73cb561ac55512eacd7b30bb4f4a11474cad526bc5db/scikit_image-0.26.0-cp314-cp314t-macosx_10_15_x86_64.whl", hash = "sha256:cde0bbd57e6795eba83cb10f71a677f7239271121dc950bc060482834a668ad1", size = 12686060, upload-time = "2025-12-20T17:12:03.886Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/e7/32/76971f8727b87f1420a962406388a50e26667c31756126444baf6668f559/scikit_image-0.26.0-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:163e9afb5b879562b9aeda0dd45208a35316f26cc7a3aed54fd601604e5cf46f", size = 12422628, upload-time = "2025-12-20T17:12:05.921Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/37/0d/996febd39f757c40ee7b01cdb861867327e5c8e5f595a634e8201462d958/scikit_image-0.26.0-cp314-cp314t-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:724f79fd9b6cb6f4a37864fe09f81f9f5d5b9646b6868109e1b100d1a7019e59", size = 12962369, upload-time = "2025-12-20T17:12:07.912Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/48/b4/612d354f946c9600e7dea012723c11d47e8d455384e530f6daaaeb9bf62c/scikit_image-0.26.0-cp314-cp314t-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:3268f13310e6857508bd87202620df996199a016a1d281b309441d227c822394", size = 13272431, upload-time = "2025-12-20T17:12:10.255Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/0a/6e/26c00b466e06055a086de2c6e2145fe189ccdc9a1d11ccc7de020f2591ad/scikit_image-0.26.0-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:fac96a1f9b06cd771cbbb3cd96c5332f36d4efd839b1d8b053f79e5887acde62", size = 14016362, upload-time = "2025-12-20T17:12:12.793Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/47/88/00a90402e1775634043c2a0af8a3c76ad450866d9fa444efcc43b553ba2d/scikit_image-0.26.0-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:2c1e7bd342f43e7a97e571b3f03ba4c1293ea1a35c3f13f41efdc8a81c1dc8f2", size = 14364151, upload-time = "2025-12-20T17:12:14.909Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/da/ca/918d8d306bd43beacff3b835c6d96fac0ae64c0857092f068b88db531a7c/scikit_image-0.26.0-cp314-cp314t-win_amd64.whl", hash = "sha256:b702c3bb115e1dcf4abf5297429b5c90f2189655888cbed14921f3d26f81d3a4", size = 12413484, upload-time = "2025-12-20T17:12:17.046Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/dc/cd/4da01329b5a8d47ff7ec3c99a2b02465a8017b186027590dc7425cee0b56/scikit_image-0.26.0-cp314-cp314t-win_arm64.whl", hash = "sha256:0608aa4a9ec39e0843de10d60edb2785a30c1c47819b67866dd223ebd149acaf", size = 11769501, upload-time = "2025-12-20T17:12:19.339Z" },
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "scikit-learn"
|
name = "scikit-learn"
|
||||||
version = "1.8.0"
|
version = "1.8.0"
|
||||||
@@ -4743,6 +4857,18 @@ wheels = [
|
|||||||
{ url = "https://files.pythonhosted.org/packages/32/d5/f9a850d79b0851d1d4ef6456097579a9005b31fea68726a4ae5f2d82ddd9/threadpoolctl-3.6.0-py3-none-any.whl", hash = "sha256:43a0b8fd5a2928500110039e43a5eed8480b918967083ea48dc3ab9f13c4a7fb", size = 18638, upload-time = "2025-03-13T13:49:21.846Z" },
|
{ url = "https://files.pythonhosted.org/packages/32/d5/f9a850d79b0851d1d4ef6456097579a9005b31fea68726a4ae5f2d82ddd9/threadpoolctl-3.6.0-py3-none-any.whl", hash = "sha256:43a0b8fd5a2928500110039e43a5eed8480b918967083ea48dc3ab9f13c4a7fb", size = 18638, upload-time = "2025-03-13T13:49:21.846Z" },
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "tifffile"
|
||||||
|
version = "2026.6.1"
|
||||||
|
source = { registry = "https://pypi.org/simple" }
|
||||||
|
dependencies = [
|
||||||
|
{ name = "numpy" },
|
||||||
|
]
|
||||||
|
sdist = { url = "https://files.pythonhosted.org/packages/b7/38/5e2ecef5af2f4fd4a89bb8d6240de9458bab4d51a4cbd97aeb3a0cd618e2/tifffile-2026.6.1.tar.gz", hash = "sha256:626c892c0e899d959b9438e7c0e1491dc154a7fead1f1f37a991724a50eceba9", size = 429694, upload-time = "2026-05-31T23:57:12.165Z" }
|
||||||
|
wheels = [
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/81/59/208f71d70ddc6184f79b8c6d87d46eb7d7b12c19186a817dec9c9c3f3693/tifffile-2026.6.1-py3-none-any.whl", hash = "sha256:0d7382d2769b855b81ce358528e2b40c16d48aa39031746efa81215205332a8d", size = 267108, upload-time = "2026-05-31T23:57:10.597Z" },
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "tinycss2"
|
name = "tinycss2"
|
||||||
version = "1.4.0"
|
version = "1.4.0"
|
||||||
@@ -4882,6 +5008,18 @@ wheels = [
|
|||||||
{ url = "https://files.pythonhosted.org/packages/b7/66/57042d4b0f1ede8046d7ae6409bf3640df996e9cbc3fe20467aa29badc54/transformers-5.1.0-py3-none-any.whl", hash = "sha256:de534b50c9b2ce6217fc56421075a1734241fb40704fdc90f50f6a08fc533d59", size = 10276537, upload-time = "2026-02-05T15:41:40.358Z" },
|
{ url = "https://files.pythonhosted.org/packages/b7/66/57042d4b0f1ede8046d7ae6409bf3640df996e9cbc3fe20467aa29badc54/transformers-5.1.0-py3-none-any.whl", hash = "sha256:de534b50c9b2ce6217fc56421075a1734241fb40704fdc90f50f6a08fc533d59", size = 10276537, upload-time = "2026-02-05T15:41:40.358Z" },
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "trimesh"
|
||||||
|
version = "4.12.2"
|
||||||
|
source = { registry = "https://pypi.org/simple" }
|
||||||
|
dependencies = [
|
||||||
|
{ name = "numpy" },
|
||||||
|
]
|
||||||
|
sdist = { url = "https://files.pythonhosted.org/packages/79/37/5cb90f04990260d2caceb6093560c6cefafca1ec522c1e43be01ca658244/trimesh-4.12.2.tar.gz", hash = "sha256:c8ca31571ac00b112e4e160e66a2d4c3491df321f056bd33806be0485d1af9d9", size = 842220, upload-time = "2026-05-01T00:57:43.333Z" }
|
||||||
|
wheels = [
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/05/98/716a473cfb24750858ddd5d14e6527539dd206583a46408d08eeb2844a75/trimesh-4.12.2-py3-none-any.whl", hash = "sha256:b5b5afa63c5272345f2858f7676bc8c217dc8a89f4fadf6193fe10a81b5ff2aa", size = 741043, upload-time = "2026-05-01T00:57:40.763Z" },
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "triton"
|
name = "triton"
|
||||||
version = "3.6.0"
|
version = "3.6.0"
|
||||||
|
|||||||
Reference in New Issue
Block a user