mirror of
https://github.com/comfyanonymous/ComfyUI.git
synced 2026-06-23 16:29:25 +08:00
Some cleanup
This commit is contained in:
parent
84ae698281
commit
ebd9c6e620
@ -144,8 +144,7 @@ class SAM3DBody_Predict(io.ComfyNode):
|
||||
"bboxes", optional=True, force_input=True,
|
||||
tooltip=(
|
||||
"Per-frame person boxes (e.g. RT-DETR Detect with class_name='person'). "
|
||||
"Used when no SAM3 track is wired — gives the top-down model a tight, "
|
||||
"person-centered crop. Multi-person supported (one box = one person)."
|
||||
"Use for better detection as alternative to SAM3 tracks."
|
||||
),
|
||||
),
|
||||
io.Boolean.Input(
|
||||
@ -154,7 +153,7 @@ class SAM3DBody_Predict(io.ComfyNode):
|
||||
io.Float.Input(
|
||||
"fov_degrees",
|
||||
default=0.0, min=0.0, max=170.0, step=0.5,
|
||||
tooltip=(
|
||||
tooltip=( #TODO: get FoV from moge another way?
|
||||
"Vertical FOV in degrees. Affects predicted depth (cam_t.z) and "
|
||||
"absolute scale. 0 = use moge_geometry or fall back to ~53° (16:9). "
|
||||
"Any non-zero value overrides moge_geometry."
|
||||
@ -164,7 +163,7 @@ class SAM3DBody_Predict(io.ComfyNode):
|
||||
"moge_geometry",
|
||||
optional=True,
|
||||
tooltip=(
|
||||
"MoGe geometry (from MoGeInference), used to calculate camera field of view."
|
||||
"MoGe geometry, used to calculate camera field of view."
|
||||
"For batches choose the most representative frame, or leave unset"
|
||||
),
|
||||
),
|
||||
@ -345,10 +344,9 @@ class SAM3DBody_FaceExpression(io.ComfyNode):
|
||||
crop_factor = 1.2
|
||||
|
||||
# Auto-pick full-frame vs per-person crops. BlazeFace full-range needs
|
||||
# ≥32px face in its 192px input; below that we escalate to per-person
|
||||
# crops. Face height ≈ 20% of body-bbox height (rough but stable).
|
||||
# ≥32px face in its 192px input; below that we escalate to per-person crops
|
||||
H_img0, W_img0 = img_np.shape[1], img_np.shape[2]
|
||||
min_bbox_px = 32.0 * max(H_img0, W_img0) / (192.0 * 0.20)
|
||||
min_bbox_px = 32.0 * max(H_img0, W_img0) / (192.0 * 0.20) # Face height ≈ 20% of body-bbox height.
|
||||
use_per_person_crops = any(
|
||||
(p["bbox"][3] - p["bbox"][1]) < min_bbox_px
|
||||
for persons in new_frames for p in persons
|
||||
@ -400,10 +398,9 @@ class SAM3DBody_FaceExpression(io.ComfyNode):
|
||||
|
||||
pbar.update(1)
|
||||
|
||||
# Baseline subtraction. MP has subject-specific rest bias (e.g.
|
||||
# naturally-raised brow at 0.15); without subtraction, strength
|
||||
# multipliers bake that into every frame. Per-clip needs ~30 frames
|
||||
# or it would zero out the expression.
|
||||
# Baseline subtraction. MP has subject-specific rest bias, without subtraction, strength
|
||||
# multipliers bake that into every frame.
|
||||
# Per-clip needs ~30 frames or it would zero out the expression.
|
||||
BASELINE_MIN_FRAMES = 30
|
||||
if n_total_frames_with_persons >= BASELINE_MIN_FRAMES:
|
||||
for pid in range(max_persons):
|
||||
@ -417,7 +414,7 @@ class SAM3DBody_FaceExpression(io.ComfyNode):
|
||||
f"got {n_total_frames_with_persons}. Skipping subtraction."
|
||||
)
|
||||
|
||||
# Smooth raw signal AFTER baseline subtraction but BEFORE gap fill —
|
||||
# Smooth raw signal AFTER baseline subtraction but BEFORE gap fill
|
||||
# MP's per-frame noise gets averaged out at the source.
|
||||
bs_win = int(blendshape_smooth_window)
|
||||
if bs_win > 1:
|
||||
@ -484,9 +481,8 @@ class SAM3DBody_Smooth(io.ComfyNode):
|
||||
options=["gaussian", "savgol"],
|
||||
default="gaussian", advanced=True,
|
||||
tooltip=(
|
||||
"'gaussian': symmetric weighted average — phase-preserving "
|
||||
"(no time-shift), best general-purpose smoother. "
|
||||
"'savgol': sliding polynomial fit — preserves sharp peaks "
|
||||
"'gaussian': symmetric weighted average, best general-purpose smoother. "
|
||||
"'savgol': sliding polynomial fit, preserves sharp peaks."
|
||||
),
|
||||
),
|
||||
io.Int.Input(
|
||||
@ -498,10 +494,9 @@ class SAM3DBody_Smooth(io.ComfyNode):
|
||||
"rotation_threshold_deg",
|
||||
default=15.0, min=0.0, max=45.0, step=1.0, advanced=True,
|
||||
tooltip=(
|
||||
"Geometry smoothing drops to RAW above this root-rotation "
|
||||
"rate (deg/frame) to preserve fast spins. 15° suits most "
|
||||
"content; low values trigger on ordinary jitter and "
|
||||
"silently sabotage smoothing. 0 = disable backoff."
|
||||
"Disables smoothing for this root-rotation rate (deg/frame) to preserve fast spins. "
|
||||
"15° suits most content, low values trigger on ordinary jitter and "
|
||||
"silently sabotage smoothing. 0 = disable."
|
||||
),
|
||||
),
|
||||
],
|
||||
@ -908,12 +903,10 @@ class SAM3DBody_Render(io.ComfyNode):
|
||||
],
|
||||
tooltip=(
|
||||
"'mesh' = 3D MHR mesh rasterized through the camera. "
|
||||
"'silhouette' = binary mask of the mesh (white-on-black, "
|
||||
"background ignored). 'openpose_2d' = flat 2D skeleton "
|
||||
"from pred_keypoints_2d (DWPose look, ControlNet-ready). "
|
||||
"'openpose_3d' = same skeleton as flat-shaded 3D capsules "
|
||||
"(camera-aware, proper depth). 'scail' = SCAIL 3D capsules "
|
||||
"via torch SDF ray-march (proper occlusion / depth)."
|
||||
"'silhouette' = binary mask of the mesh. "
|
||||
"'openpose_2d' = flat 2D skeleton "
|
||||
"'openpose_3d' = openpose skeleton as flat-shaded 3D model "
|
||||
"'scail' = SCAIL 3D capsules "
|
||||
),
|
||||
),
|
||||
],
|
||||
|
||||
@ -425,6 +425,21 @@ def rainbow_tilt_inputs():
|
||||
]
|
||||
|
||||
|
||||
def camera_translation_input():
|
||||
"""Shared camera_translation combo (BuildPoseGLB + SavePoseBVH)."""
|
||||
return IO.Combo.Input(
|
||||
"camera_translation",
|
||||
options=["off", "centered", "absolute"],
|
||||
default="off",
|
||||
tooltip=(
|
||||
"Bake pred_cam_t into the root's translation "
|
||||
"'off' = bind position "
|
||||
"'centered' = delta from frame 0 "
|
||||
"'absolute' = raw (Z is camera depth — usually meters away)."
|
||||
),
|
||||
)
|
||||
|
||||
|
||||
class BuildPoseGLB(IO.ComfyNode):
|
||||
"""Convert pose_data to an in-memory animated GLB"""
|
||||
|
||||
@ -438,24 +453,13 @@ class BuildPoseGLB(IO.ComfyNode):
|
||||
inputs=[
|
||||
IO.MultiType.Input(
|
||||
"pose_data", types=[MHRPoseData, KimodoPoseData],
|
||||
tooltip=(
|
||||
"MHR pose data from SAM3DBody_Predict, or external-rig "
|
||||
"pose data from Kimodo (`_skeleton_override`-augmented)."
|
||||
),
|
||||
tooltip=("MHR pose data from SAM3DBody_Predict, Kimodo. "),
|
||||
),
|
||||
SAM3DBodyModel.Input("sam3d_body_model", optional=True),
|
||||
IO.DynamicCombo.Input(
|
||||
"mesh_style",
|
||||
options=[
|
||||
IO.DynamicCombo.Option("body_mesh", [
|
||||
IO.Int.Input(
|
||||
"bone_smooth_window",
|
||||
default=0, min=0, max=51, step=2,
|
||||
tooltip=(
|
||||
"Gaussian window on per-bone rotation keyframes. 0 = off. "
|
||||
"7-15 helps cartwheels/spins where upstream Smooth misses spikes."
|
||||
),
|
||||
),
|
||||
IO.DynamicCombo.Input(
|
||||
"bone_vis",
|
||||
options=[
|
||||
@ -485,11 +489,7 @@ class BuildPoseGLB(IO.ComfyNode):
|
||||
),
|
||||
]),
|
||||
],
|
||||
tooltip=(
|
||||
"Bone vis shape, rigidly skinned to each joint. "
|
||||
"'octahedrons' = Blender-style directional bones (joint → "
|
||||
"primary child); 'sticks' = thin lines."
|
||||
),
|
||||
tooltip=("Bone vis shape, rigidly skinned to each joint. "),
|
||||
),
|
||||
IO.DynamicCombo.Input(
|
||||
"shader",
|
||||
@ -500,7 +500,7 @@ class BuildPoseGLB(IO.ComfyNode):
|
||||
IO.Float.Input(
|
||||
"person_palette_falloff",
|
||||
default=0.6, min=0.1, max=1.0, step=0.05,
|
||||
tooltip="Per-person desaturation: track k gets (1 - falloff^k) pastel mix.",
|
||||
tooltip="Per-person desaturation: each track gets (1 - falloff^k) pastel mix.",
|
||||
),
|
||||
]),
|
||||
IO.DynamicCombo.Option("rainbow_face_normal", [
|
||||
@ -508,7 +508,7 @@ class BuildPoseGLB(IO.ComfyNode):
|
||||
IO.Float.Input(
|
||||
"person_palette_falloff",
|
||||
default=0.6, min=0.1, max=1.0, step=0.05,
|
||||
tooltip="Per-person desaturation: track k gets (1 - falloff^k) pastel mix.",
|
||||
tooltip="Per-person desaturation: each track gets (1 - falloff^k) pastel mix.",
|
||||
),
|
||||
]),
|
||||
IO.DynamicCombo.Option("rainbow_face_semantic", [
|
||||
@ -516,7 +516,7 @@ class BuildPoseGLB(IO.ComfyNode):
|
||||
IO.Float.Input(
|
||||
"person_palette_falloff",
|
||||
default=0.6, min=0.1, max=1.0, step=0.05,
|
||||
tooltip="Per-person desaturation: track k gets (1 - falloff^k) pastel mix.",
|
||||
tooltip="Per-person desaturation: each track gets (1 - falloff^k) pastel mix.",
|
||||
),
|
||||
]),
|
||||
],
|
||||
@ -527,14 +527,6 @@ class BuildPoseGLB(IO.ComfyNode):
|
||||
),
|
||||
]),
|
||||
IO.DynamicCombo.Option("bones_only", [
|
||||
IO.Int.Input(
|
||||
"bone_smooth_window",
|
||||
default=0, min=0, max=51, step=2,
|
||||
tooltip=(
|
||||
"Gaussian window on per-bone rotation keyframes. 0 = off. "
|
||||
"7-15 helps cartwheels/spins where upstream Smooth misses spikes."
|
||||
),
|
||||
),
|
||||
IO.DynamicCombo.Input(
|
||||
"bone_vis",
|
||||
options=[
|
||||
@ -571,14 +563,6 @@ class BuildPoseGLB(IO.ComfyNode):
|
||||
),
|
||||
]),
|
||||
IO.DynamicCombo.Option("openpose", [
|
||||
IO.Int.Input(
|
||||
"bone_smooth_window",
|
||||
default=0, min=0, max=51, step=2,
|
||||
tooltip=(
|
||||
"Gaussian window on keypoint tracks. 0 = off. "
|
||||
"7-15 calms jitter where upstream Smooth misses spikes."
|
||||
),
|
||||
),
|
||||
IO.Float.Input(
|
||||
"marker_radius_m", default=0.010, min=0.005, max=0.1, step=0.001, advanced=True,
|
||||
tooltip="Sphere radius in m.",
|
||||
@ -618,14 +602,6 @@ class BuildPoseGLB(IO.ComfyNode):
|
||||
),
|
||||
]),
|
||||
IO.DynamicCombo.Option("scail", [
|
||||
IO.Int.Input(
|
||||
"bone_smooth_window",
|
||||
default=0, min=0, max=51, step=2,
|
||||
tooltip=(
|
||||
"Gaussian window on keypoint tracks. 0 = off. "
|
||||
"7-15 calms jitter where upstream Smooth misses spikes."
|
||||
),
|
||||
),
|
||||
IO.Float.Input(
|
||||
"stick_radius_m", default=0.022, min=0.002, max=0.1, step=0.001, advanced=True,
|
||||
tooltip=(
|
||||
@ -667,28 +643,25 @@ class BuildPoseGLB(IO.ComfyNode):
|
||||
]),
|
||||
],
|
||||
tooltip=(
|
||||
"'body_mesh' = real Armature (127 bones, skinning, TRS "
|
||||
"keyframes, 72 face morphs; needs model). "
|
||||
"'body_mesh' = real Armature (127 bones, skinning, TRS keyframes, 72 face morphs; needs model). "
|
||||
"'bones_only' = bone-shape primitives at each joint (preview armature). "
|
||||
"'openpose' = OpenPose-18 3D skeleton from keypoints "
|
||||
"(no model needed). 'scail' = SCAIL 3D capsule rig (open "
|
||||
"cylinders capped flush by joint spheres)."
|
||||
"'scail' = SCAIL 3D capsule rig (open cylinders capped flush by joint spheres)."
|
||||
),
|
||||
),
|
||||
IO.Int.Input(
|
||||
"bone_smooth_window",
|
||||
default=0, min=0, max=51, step=2,
|
||||
tooltip=(
|
||||
"Gaussian smoothing window on per-bone rotation keyframes / keypoint "
|
||||
"tracks. 0 = off. 7-15 calms spins/jitter where upstream Smooth misses spikes."
|
||||
),
|
||||
),
|
||||
IO.Float.Input(
|
||||
"fps", default=24.0, min=1.0, max=240.0, step=1.0,
|
||||
tooltip="Animation frame rate.",
|
||||
),
|
||||
IO.Combo.Input(
|
||||
"camera_translation",
|
||||
options=["off", "centered", "absolute"],
|
||||
default="off",
|
||||
tooltip=(
|
||||
"Bake pred_cam_t into per-track root translation. "
|
||||
"'off' = origin; 'centered' = delta from frame 0; "
|
||||
"'absolute' = raw (Z is camera depth — usually meters away)."
|
||||
),
|
||||
),
|
||||
camera_translation_input(),
|
||||
IO.Int.Input(
|
||||
"track_index", default=-1, min=-1, max=15,
|
||||
tooltip="-1 = all tracks; ≥0 = single track.",
|
||||
@ -698,7 +671,7 @@ class BuildPoseGLB(IO.ComfyNode):
|
||||
)
|
||||
|
||||
@classmethod
|
||||
def execute(cls, pose_data, mesh_style, sam3d_body_model=None, fps=24.0, camera_translation="off", track_index=-1) -> IO.NodeOutput:
|
||||
def execute(cls, pose_data, mesh_style, sam3d_body_model=None, bone_smooth_window=0, fps=24.0, camera_translation="off", track_index=-1) -> IO.NodeOutput:
|
||||
mesh_style = mesh_style or {"mesh_style": "body_mesh"}
|
||||
mode_key = mesh_style["mesh_style"]
|
||||
# `shader` is nested in body_mesh; absent for bones_only.
|
||||
@ -730,7 +703,7 @@ class BuildPoseGLB(IO.ComfyNode):
|
||||
bone_vis_color = str(bone_vis_dict.get("bone_vis_color", "white"))
|
||||
glb_bytes = build_glb_skeletal(
|
||||
pose_data, sam3d_body_model,
|
||||
bone_smooth_window=int(mesh_style.get("bone_smooth_window", 0)),
|
||||
bone_smooth_window=int(bone_smooth_window),
|
||||
bone_vis=bone_vis,
|
||||
bone_vis_radius_m=bone_vis_radius_m,
|
||||
bone_vis_color=bone_vis_color,
|
||||
@ -754,7 +727,7 @@ class BuildPoseGLB(IO.ComfyNode):
|
||||
face_marker_radius_m=float(mesh_style.get("face_marker_radius_m", 0.0)),
|
||||
palette="openpose",
|
||||
shape="ellipsoid",
|
||||
bone_smooth_window=int(mesh_style.get("bone_smooth_window", 0)),
|
||||
bone_smooth_window=int(bone_smooth_window),
|
||||
)
|
||||
elif mode_key == "scail":
|
||||
# SCAIL rig: open cylinders capped flush by joint spheres (sphere
|
||||
@ -781,7 +754,7 @@ class BuildPoseGLB(IO.ComfyNode):
|
||||
# inside of the open cylinders shades sensibly at grazing angles.
|
||||
material_roughness=float(mesh_style.get("material_roughness", 0.3)),
|
||||
material_double_sided=True,
|
||||
bone_smooth_window=int(mesh_style.get("bone_smooth_window", 0)),
|
||||
bone_smooth_window=int(bone_smooth_window),
|
||||
)
|
||||
else:
|
||||
raise ValueError(f"BuildPoseGLB: unknown mesh_style {mode_key!r}")
|
||||
@ -813,16 +786,7 @@ class SavePoseBVH(IO.ComfyNode):
|
||||
"fps", default=24.0, min=1.0, max=240.0, step=1.0,
|
||||
tooltip="Animation frame rate (BVH `Frame Time`).",
|
||||
),
|
||||
IO.Combo.Input(
|
||||
"camera_translation",
|
||||
options=["off", "centered", "absolute"],
|
||||
default="off",
|
||||
tooltip=(
|
||||
"Bake pred_cam_t into the root's position channels. "
|
||||
"'off' = bind position; 'centered' = delta from frame 0; "
|
||||
"'absolute' = raw (Z is camera depth — usually meters away)."
|
||||
),
|
||||
),
|
||||
camera_translation_input(),
|
||||
IO.Combo.Input(
|
||||
"units",
|
||||
options=["cm", "m"],
|
||||
|
||||
Loading…
Reference in New Issue
Block a user