feat(cutout_tool): Implement cutout region to shape functionality

- Added interaction helpers for cutout region validation and shape menu interaction.
- Created main operator for converting image regions into cutout shapes, including AI artifact generation.
- Introduced object creation logic for cutout shapes, handling depth and normal textures.
- Defined cutout shape identifiers and node groups for various shape types.
- Implemented depth texture writing and prediction artifact generation for MoGe-2.
- Developed server jobs for generating cutout artifacts, depth planes, and refining image regions.
- Added region refinement logic to enhance gesture masks using BEN2.
This commit is contained in:
2026-08-31 11:36:27 +08:00
parent 08309f719d
commit 87d7721128
80 changed files with 4823 additions and 4297 deletions

View File

@@ -1,4 +1,3 @@
from dataclasses import dataclass
from pathlib import Path
import bpy
@@ -11,49 +10,6 @@ from .image_data import (
)
@dataclass(frozen=True)
class ImageGeometry:
points: object
intrinsics: object
valid: object
calibration_valid: object
image_size: tuple
reference_depth: float
region_transparent_fraction: float
def load_image_geometry(path):
"""Load and validate the shared image geometry Job artifact."""
import numpy as np
with np.load(path, allow_pickle=False) as archive:
geometry = ImageGeometry(
points=np.asarray(archive["points"], dtype=np.float32),
intrinsics=np.asarray(archive["intrinsics"], dtype=np.float32),
valid=np.asarray(archive["valid"], dtype=bool),
calibration_valid=np.asarray(archive["calibration_valid"], dtype=bool),
image_size=tuple(int(value) for value in archive["image_size"]),
reference_depth=float(archive["reference_depth"]),
region_transparent_fraction=float(
archive["region_transparent_fraction"]
),
)
if (
geometry.points.ndim != 3
or geometry.points.shape[2] != 3
or geometry.valid.shape != geometry.points.shape[:2]
or geometry.calibration_valid.shape != geometry.points.shape[:2]
):
raise ValueError("The mesh point field is invalid")
if (
geometry.intrinsics.shape != (3, 3)
or not geometry.reference_depth > 0.0
or not 0.0 <= geometry.region_transparent_fraction <= 1.0
):
raise ValueError("The mesh camera field is invalid")
return geometry
NODE_ASSET_NAME = "O_AnyImage.blend"
@@ -161,12 +117,9 @@ def set_material_color_space(image, scene=None):
preferred = material_color_space_name(scene)
original = settings.name
pixels = None
if (
preferred != original
and (
getattr(image, "source", None) == "GENERATED"
or getattr(image, "is_dirty", False)
)
if preferred != original and (
getattr(image, "source", None) == "GENERATED"
or getattr(image, "is_dirty", False)
):
pixels = image_pixels(image)
for color_space in dict.fromkeys((preferred, "sRGB", original)):
@@ -389,6 +342,7 @@ def create_image_material(
use_cyclic=None,
normal_image=None,
normal_space="TANGENT",
ior=None,
scene=None,
):
material = bpy.data.materials.new(image_base_name(source_object.data))
@@ -483,6 +437,8 @@ def create_image_material(
else:
shader = nodes.new("ShaderNodeBsdfPrincipled")
shader.location = (250.0, 400.0)
if ior is not None:
shader.inputs["IOR"].default_value = float(ior)
links.new(
material_inputs.outputs["Color"],