feat(ml): auto-commit con 7 cambios

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-06-24 02:05:43 +02:00
parent 337f75b527
commit 3823a28d1c
7 changed files with 611 additions and 0 deletions
@@ -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))
+3
View File
@@ -21,6 +21,7 @@ dependencies = [
"matplotlib>=3.10.9",
"openpyxl>=3.1.5",
"polars>=1.40.1",
"pymeshlab>=2025.7.post1",
"pymssql>=2.3.13",
"pypdf>=6.10.0",
"pyproj>=3.7.2",
@@ -28,10 +29,12 @@ dependencies = [
"pyyaml>=6.0.3",
"rapidfuzz>=3.14.5",
"reportlab>=4.5.0",
"scikit-image>=0.26.0",
"scikit-learn>=1.8.0",
"scipy>=1.17.1",
"seaborn>=0.13.2",
"shapely>=2.1.2",
"trimesh>=4.12.2",
"xlrd>=2.0.2",
]
+138
View File
@@ -902,6 +902,7 @@ dependencies = [
{ name = "matplotlib" },
{ name = "openpyxl" },
{ name = "polars" },
{ name = "pymeshlab" },
{ name = "pymssql" },
{ name = "pypdf" },
{ name = "pyproj" },
@@ -909,10 +910,12 @@ dependencies = [
{ name = "pyyaml" },
{ name = "rapidfuzz" },
{ name = "reportlab" },
{ name = "scikit-image" },
{ name = "scikit-learn" },
{ name = "scipy" },
{ name = "seaborn" },
{ name = "shapely" },
{ name = "trimesh" },
{ name = "xlrd" },
]
@@ -955,6 +958,7 @@ requires-dist = [
{ name = "matplotlib", specifier = ">=3.10.9" },
{ name = "openpyxl", specifier = ">=3.1.5" },
{ name = "polars", specifier = ">=1.40.1" },
{ name = "pymeshlab", specifier = ">=2025.7.post1" },
{ name = "pymssql", specifier = ">=2.3.13" },
{ name = "pypdf", specifier = ">=6.10.0" },
{ name = "pyproj", specifier = ">=3.7.2" },
@@ -962,10 +966,12 @@ requires-dist = [
{ name = "pyyaml", specifier = ">=6.0.3" },
{ name = "rapidfuzz", specifier = ">=3.14.5" },
{ name = "reportlab", specifier = ">=4.5.0" },
{ name = "scikit-image", specifier = ">=0.26.0" },
{ name = "scikit-learn", specifier = ">=1.8.0" },
{ name = "scipy", specifier = ">=1.17.1" },
{ name = "seaborn", specifier = ">=0.13.2" },
{ name = "shapely", specifier = ">=2.1.2" },
{ name = "trimesh", specifier = ">=4.12.2" },
{ name = "xlrd", specifier = ">=2.0.2" },
]
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" },
]
[[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]]
name = "iniconfig"
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" },
]
[[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]]
name = "lxml"
version = "6.0.2"
@@ -3627,6 +3658,31 @@ crypto = [
{ 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]]
name = "pymssql"
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" },
]
[[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]]
name = "scikit-learn"
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" },
]
[[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]]
name = "tinycss2"
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" },
]
[[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]]
name = "triton"
version = "3.6.0"