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:
@@ -1,21 +1,21 @@
|
||||
"""Generate optional AI data for one Blender-rasterized Cutout Region."""
|
||||
"""Generate optional AI files for one Blender-rasterized Cutout Region."""
|
||||
|
||||
import json
|
||||
from pathlib import Path
|
||||
|
||||
from ..geometry.generate_depth import generate_depth
|
||||
from ..region import generate_selection
|
||||
from ..geometry.prediction_artifacts import generate_moge2_artifacts
|
||||
from ..region import refine_region
|
||||
|
||||
|
||||
def run(context, parameters):
|
||||
context.progress(0.05, "Preparing Cutout Region")
|
||||
context.directory.mkdir(parents=True, exist_ok=True)
|
||||
input_path = Path(parameters["input"])
|
||||
region_path = input_path
|
||||
region_image_path = input_path
|
||||
result = {}
|
||||
if parameters.get("refine_region"):
|
||||
context.progress(0.2, "Generating refined Region")
|
||||
region_path, bounds = generate_selection(
|
||||
context.progress(0.2, "Refining Region")
|
||||
region_image_path, bounds = refine_region(
|
||||
context,
|
||||
input_path,
|
||||
parameters["refine_model"],
|
||||
@@ -28,24 +28,21 @@ def run(context, parameters):
|
||||
encoding="utf-8",
|
||||
)
|
||||
result.update(
|
||||
region=region_path.name,
|
||||
region_image=region_image_path.name,
|
||||
region_bounds=bounds_path.name,
|
||||
)
|
||||
|
||||
output_depth = bool(parameters.get("output_depth"))
|
||||
depth_mode = str(parameters.get("depth_mode", "NONE"))
|
||||
normal_mode = str(parameters.get("normal_mode", "NONE"))
|
||||
if output_depth or normal_mode != "NONE":
|
||||
archive_path, normal_path = generate_depth(
|
||||
if depth_mode != "NONE" or normal_mode != "NONE":
|
||||
artifacts = generate_moge2_artifacts(
|
||||
context,
|
||||
parameters,
|
||||
region_path,
|
||||
output_depth=output_depth,
|
||||
region_image_path,
|
||||
depth_mode=depth_mode,
|
||||
normal_mode=normal_mode,
|
||||
)
|
||||
if archive_path is not None:
|
||||
result["image_geometry"] = archive_path.name
|
||||
if normal_path is not None:
|
||||
result["normal"] = normal_path.name
|
||||
result.update({key: path.name for key, path in artifacts.items()})
|
||||
context.check_cancelled()
|
||||
context.progress(1.0, "Cutout Region data is ready")
|
||||
context.progress(1.0, "Cutout artifacts are ready")
|
||||
return result
|
||||
@@ -1,6 +1,6 @@
|
||||
"""Generate depth data and preserve color for one complete image."""
|
||||
"""Generate model-space Z Depth and preserve color for one complete image."""
|
||||
|
||||
from ..geometry.generate_depth import generate_depth
|
||||
from ..geometry.prediction_artifacts import generate_moge2_artifacts
|
||||
from ..media import copy_color_images, input_frames
|
||||
|
||||
|
||||
@@ -11,12 +11,12 @@ def run(context, parameters):
|
||||
if len(images) != 1:
|
||||
raise ValueError("Depth Plane currently supports one image")
|
||||
copy_color_images(images, context.directory)
|
||||
archive_path, _normal_path = generate_depth(
|
||||
artifacts = generate_moge2_artifacts(
|
||||
context,
|
||||
parameters,
|
||||
images[0],
|
||||
output_depth=True,
|
||||
depth_mode="Z",
|
||||
)
|
||||
context.check_cancelled()
|
||||
context.progress(1.0, "Depth Plane data is ready")
|
||||
return {"image_geometry": archive_path.name}
|
||||
return {key: path.name for key, path in artifacts.items()}
|
||||
@@ -1,18 +1,18 @@
|
||||
import json
|
||||
import time
|
||||
|
||||
from ..region import generate_selection
|
||||
from ..region import refine_region
|
||||
|
||||
|
||||
def run(context, parameters):
|
||||
"""Refine a gesture mask with BEN2 and return its source-image bounds."""
|
||||
started = time.perf_counter()
|
||||
context.progress(0.05, "Preparing image selection")
|
||||
context.progress(0.05, "Preparing image Region")
|
||||
context.check_cancelled()
|
||||
output_directory = context.directory
|
||||
output_directory.mkdir(parents=True, exist_ok=True)
|
||||
context.progress(0.2, f"Loading BEN2 for {parameters['device'].upper()}")
|
||||
output_path, bounds = generate_selection(
|
||||
output_path, bounds = refine_region(
|
||||
context,
|
||||
parameters["input"],
|
||||
parameters["model"],
|
||||
@@ -22,6 +22,6 @@ def run(context, parameters):
|
||||
bounds_path = output_directory / "bounds.json"
|
||||
bounds_path.write_text(json.dumps(bounds, separators=(",", ":")), encoding="utf-8")
|
||||
elapsed_ms = (time.perf_counter() - started) * 1000.0
|
||||
message = f"Image selection refined in {elapsed_ms:.0f} ms"
|
||||
message = f"Image Region refined in {elapsed_ms:.0f} ms"
|
||||
context.progress(1.0, message)
|
||||
return {"image": output_path.name, "bounds": bounds_path.name}
|
||||
return {"region_image": output_path.name, "region_bounds": bounds_path.name}
|
||||
Reference in New Issue
Block a user