mirror of
https://github.com/comfyanonymous/ComfyUI.git
synced 2026-04-18 22:42:35 +08:00
remove(isolation): drop internal ply and npz support
This commit is contained in:
parent
b1bcaaf8fe
commit
3b0fc0ab87
@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
Drop-in replacement for comfy_api.latest._util type imports in sealed workers
|
Drop-in replacement for comfy_api.latest._util type imports in sealed workers
|
||||||
that do not have torch installed. Contains only data type definitions (TrimeshData,
|
that do not have torch installed. Contains only data type definitions (TrimeshData,
|
||||||
PLY, NPZ, etc.) with numpy-only dependencies.
|
etc.) with numpy-only dependencies.
|
||||||
|
|
||||||
Usage in serializers:
|
Usage in serializers:
|
||||||
if _IMPORT_TORCH:
|
if _IMPORT_TORCH:
|
||||||
@ -12,7 +12,5 @@ Usage in serializers:
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
from .trimesh_types import TrimeshData
|
from .trimesh_types import TrimeshData
|
||||||
from .ply_types import PLY
|
|
||||||
from .npz_types import NPZ
|
|
||||||
|
|
||||||
__all__ = ["TrimeshData", "PLY", "NPZ"]
|
__all__ = ["TrimeshData"]
|
||||||
|
|||||||
@ -1,27 +0,0 @@
|
|||||||
from __future__ import annotations
|
|
||||||
|
|
||||||
import os
|
|
||||||
|
|
||||||
|
|
||||||
class NPZ:
|
|
||||||
"""Ordered collection of NPZ file payloads.
|
|
||||||
|
|
||||||
Each entry in ``frames`` is a complete compressed ``.npz`` file stored
|
|
||||||
as raw bytes (produced by ``numpy.savez_compressed`` into a BytesIO).
|
|
||||||
``save_to`` writes numbered files into a directory.
|
|
||||||
"""
|
|
||||||
|
|
||||||
def __init__(self, frames: list[bytes]) -> None:
|
|
||||||
self.frames = frames
|
|
||||||
|
|
||||||
@property
|
|
||||||
def num_frames(self) -> int:
|
|
||||||
return len(self.frames)
|
|
||||||
|
|
||||||
def save_to(self, directory: str, prefix: str = "frame") -> str:
|
|
||||||
os.makedirs(directory, exist_ok=True)
|
|
||||||
for i, frame_bytes in enumerate(self.frames):
|
|
||||||
path = os.path.join(directory, f"{prefix}_{i:06d}.npz")
|
|
||||||
with open(path, "wb") as f:
|
|
||||||
f.write(frame_bytes)
|
|
||||||
return directory
|
|
||||||
@ -1,97 +0,0 @@
|
|||||||
from __future__ import annotations
|
|
||||||
|
|
||||||
import numpy as np
|
|
||||||
|
|
||||||
|
|
||||||
class PLY:
|
|
||||||
"""Point cloud payload for PLY file output.
|
|
||||||
|
|
||||||
Supports two schemas:
|
|
||||||
- Pointcloud: xyz positions with optional colors, confidence, view_id (ASCII format)
|
|
||||||
- Gaussian: raw binary PLY data built by producer nodes using plyfile (binary format)
|
|
||||||
|
|
||||||
When ``raw_data`` is provided, the object acts as an opaque binary PLY
|
|
||||||
carrier and ``save_to`` writes the bytes directly.
|
|
||||||
"""
|
|
||||||
|
|
||||||
def __init__(
|
|
||||||
self,
|
|
||||||
points: np.ndarray | None = None,
|
|
||||||
colors: np.ndarray | None = None,
|
|
||||||
confidence: np.ndarray | None = None,
|
|
||||||
view_id: np.ndarray | None = None,
|
|
||||||
raw_data: bytes | None = None,
|
|
||||||
) -> None:
|
|
||||||
self.raw_data = raw_data
|
|
||||||
if raw_data is not None:
|
|
||||||
self.points = None
|
|
||||||
self.colors = None
|
|
||||||
self.confidence = None
|
|
||||||
self.view_id = None
|
|
||||||
return
|
|
||||||
if points is None:
|
|
||||||
raise ValueError("Either points or raw_data must be provided")
|
|
||||||
if points.ndim != 2 or points.shape[1] != 3:
|
|
||||||
raise ValueError(f"points must be (N, 3), got {points.shape}")
|
|
||||||
self.points = np.ascontiguousarray(points, dtype=np.float32)
|
|
||||||
self.colors = np.ascontiguousarray(colors, dtype=np.float32) if colors is not None else None
|
|
||||||
self.confidence = np.ascontiguousarray(confidence, dtype=np.float32) if confidence is not None else None
|
|
||||||
self.view_id = np.ascontiguousarray(view_id, dtype=np.int32) if view_id is not None else None
|
|
||||||
|
|
||||||
@property
|
|
||||||
def is_gaussian(self) -> bool:
|
|
||||||
return self.raw_data is not None
|
|
||||||
|
|
||||||
@property
|
|
||||||
def num_points(self) -> int:
|
|
||||||
if self.points is not None:
|
|
||||||
return self.points.shape[0]
|
|
||||||
return 0
|
|
||||||
|
|
||||||
@staticmethod
|
|
||||||
def _to_numpy(arr, dtype):
|
|
||||||
if arr is None:
|
|
||||||
return None
|
|
||||||
if hasattr(arr, "numpy"):
|
|
||||||
arr = arr.cpu().numpy() if hasattr(arr, "cpu") else arr.numpy()
|
|
||||||
return np.ascontiguousarray(arr, dtype=dtype)
|
|
||||||
|
|
||||||
def save_to(self, path: str) -> str:
|
|
||||||
if self.raw_data is not None:
|
|
||||||
with open(path, "wb") as f:
|
|
||||||
f.write(self.raw_data)
|
|
||||||
return path
|
|
||||||
self.points = self._to_numpy(self.points, np.float32)
|
|
||||||
self.colors = self._to_numpy(self.colors, np.float32)
|
|
||||||
self.confidence = self._to_numpy(self.confidence, np.float32)
|
|
||||||
self.view_id = self._to_numpy(self.view_id, np.int32)
|
|
||||||
N = self.num_points
|
|
||||||
header_lines = [
|
|
||||||
"ply",
|
|
||||||
"format ascii 1.0",
|
|
||||||
f"element vertex {N}",
|
|
||||||
"property float x",
|
|
||||||
"property float y",
|
|
||||||
"property float z",
|
|
||||||
]
|
|
||||||
if self.colors is not None:
|
|
||||||
header_lines += ["property uchar red", "property uchar green", "property uchar blue"]
|
|
||||||
if self.confidence is not None:
|
|
||||||
header_lines.append("property float confidence")
|
|
||||||
if self.view_id is not None:
|
|
||||||
header_lines.append("property int view_id")
|
|
||||||
header_lines.append("end_header")
|
|
||||||
|
|
||||||
with open(path, "w") as f:
|
|
||||||
f.write("\n".join(header_lines) + "\n")
|
|
||||||
for i in range(N):
|
|
||||||
parts = [f"{self.points[i, 0]} {self.points[i, 1]} {self.points[i, 2]}"]
|
|
||||||
if self.colors is not None:
|
|
||||||
r, g, b = (self.colors[i] * 255).clip(0, 255).astype(np.uint8)
|
|
||||||
parts.append(f"{r} {g} {b}")
|
|
||||||
if self.confidence is not None:
|
|
||||||
parts.append(f"{self.confidence[i]}")
|
|
||||||
if self.view_id is not None:
|
|
||||||
parts.append(f"{int(self.view_id[i])}")
|
|
||||||
f.write(" ".join(parts) + "\n")
|
|
||||||
return path
|
|
||||||
@ -1,40 +0,0 @@
|
|||||||
import os
|
|
||||||
|
|
||||||
import folder_paths
|
|
||||||
from comfy_api.latest import io
|
|
||||||
from comfy_api_sealed_worker.npz_types import NPZ
|
|
||||||
|
|
||||||
|
|
||||||
class SaveNPZ(io.ComfyNode):
|
|
||||||
@classmethod
|
|
||||||
def define_schema(cls):
|
|
||||||
return io.Schema(
|
|
||||||
node_id="SaveNPZ",
|
|
||||||
display_name="Save NPZ",
|
|
||||||
category="3d",
|
|
||||||
is_output_node=True,
|
|
||||||
inputs=[
|
|
||||||
io.Npz.Input("npz"),
|
|
||||||
io.String.Input("filename_prefix", default="da3_streaming/ComfyUI"),
|
|
||||||
],
|
|
||||||
)
|
|
||||||
|
|
||||||
@classmethod
|
|
||||||
def execute(cls, npz: NPZ, filename_prefix: str) -> io.NodeOutput:
|
|
||||||
full_output_folder, filename, counter, subfolder, _ = folder_paths.get_save_image_path(
|
|
||||||
filename_prefix, folder_paths.get_output_directory()
|
|
||||||
)
|
|
||||||
batch_dir = os.path.join(full_output_folder, f"{filename}_{counter:05}")
|
|
||||||
os.makedirs(batch_dir, exist_ok=True)
|
|
||||||
filenames = []
|
|
||||||
for i, frame_bytes in enumerate(npz.frames):
|
|
||||||
f = f"frame_{i:06d}.npz"
|
|
||||||
with open(os.path.join(batch_dir, f), "wb") as fh:
|
|
||||||
fh.write(frame_bytes)
|
|
||||||
filenames.append(f)
|
|
||||||
return io.NodeOutput(ui={"npz_files": [{"folder": os.path.join(subfolder, f"{filename}_{counter:05}"), "count": len(filenames), "type": "output"}]})
|
|
||||||
|
|
||||||
|
|
||||||
NODE_CLASS_MAPPINGS = {
|
|
||||||
"SaveNPZ": SaveNPZ,
|
|
||||||
}
|
|
||||||
@ -1,34 +0,0 @@
|
|||||||
import os
|
|
||||||
|
|
||||||
import folder_paths
|
|
||||||
from comfy_api.latest import io
|
|
||||||
from comfy_api_sealed_worker.ply_types import PLY
|
|
||||||
|
|
||||||
|
|
||||||
class SavePLY(io.ComfyNode):
|
|
||||||
@classmethod
|
|
||||||
def define_schema(cls):
|
|
||||||
return io.Schema(
|
|
||||||
node_id="SavePLY",
|
|
||||||
display_name="Save PLY",
|
|
||||||
category="3d",
|
|
||||||
is_output_node=True,
|
|
||||||
inputs=[
|
|
||||||
io.Ply.Input("ply"),
|
|
||||||
io.String.Input("filename_prefix", default="pointcloud/ComfyUI"),
|
|
||||||
],
|
|
||||||
)
|
|
||||||
|
|
||||||
@classmethod
|
|
||||||
def execute(cls, ply: PLY, filename_prefix: str) -> io.NodeOutput:
|
|
||||||
full_output_folder, filename, counter, subfolder, _ = folder_paths.get_save_image_path(
|
|
||||||
filename_prefix, folder_paths.get_output_directory()
|
|
||||||
)
|
|
||||||
f = f"{filename}_{counter:05}_.ply"
|
|
||||||
ply.save_to(os.path.join(full_output_folder, f))
|
|
||||||
return io.NodeOutput(ui={"pointclouds": [{"filename": f, "subfolder": subfolder, "type": "output"}]})
|
|
||||||
|
|
||||||
|
|
||||||
NODE_CLASS_MAPPINGS = {
|
|
||||||
"SavePLY": SavePLY,
|
|
||||||
}
|
|
||||||
2
nodes.py
2
nodes.py
@ -2459,8 +2459,6 @@ async def init_builtin_extra_nodes():
|
|||||||
"nodes_wan.py",
|
"nodes_wan.py",
|
||||||
"nodes_lotus.py",
|
"nodes_lotus.py",
|
||||||
"nodes_hunyuan3d.py",
|
"nodes_hunyuan3d.py",
|
||||||
"nodes_save_ply.py",
|
|
||||||
"nodes_save_npz.py",
|
|
||||||
"nodes_primitive.py",
|
"nodes_primitive.py",
|
||||||
"nodes_cfg.py",
|
"nodes_cfg.py",
|
||||||
"nodes_optimalsteps.py",
|
"nodes_optimalsteps.py",
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user