Add cutout profile and teddy balloon height calculations
- Implemented cotangent Poisson field and Poisson balloon profile in cutout_profile.py. - Added teddy balloon heights calculation and related functions in cutout_teddy.py. - Introduced interaction utilities for image editing in interaction.py. - Developed depth normalization and analysis functions in cutout_depth.py. - Created a validation script for cutout assets in validate_cutout_asset.py.
This commit is contained in:
@@ -18,6 +18,15 @@ UPSCALE_MODEL_ITEMS = tuple(
|
||||
for index, model in enumerate(UPSCALE_MODELS.values())
|
||||
)
|
||||
|
||||
BALLOON_PROFILE_ALGORITHM_ITEMS = (
|
||||
(
|
||||
"POISSON",
|
||||
"Poisson",
|
||||
"Smooth cotangent-Laplacian Balloon profile",
|
||||
),
|
||||
("TEDDY", "Teddy", "Chordal-axis Balloon profile"),
|
||||
)
|
||||
|
||||
|
||||
def addon_preferences(context=None):
|
||||
preference_context = (
|
||||
@@ -85,6 +94,12 @@ class AnyImagePreferences(bpy.types.AddonPreferences):
|
||||
step=256,
|
||||
subtype="PIXEL",
|
||||
)
|
||||
balloon_profile_algorithm: bpy.props.EnumProperty(
|
||||
name="Balloon Profile",
|
||||
description="Algorithm used to generate o_balloon for every Cutout shape",
|
||||
items=BALLOON_PROFILE_ALGORITHM_ITEMS,
|
||||
default="POISSON",
|
||||
)
|
||||
mesh_depth_model: bpy.props.EnumProperty(
|
||||
name="Mesh Depth Model",
|
||||
description="Depth model used by Depth Plane, Depth Balloon and Depth Surface",
|
||||
@@ -114,20 +129,12 @@ class AnyImagePreferences(bpy.types.AddonPreferences):
|
||||
from .runtime import runtime
|
||||
|
||||
layout = self.layout
|
||||
status = ai_status()
|
||||
models = {model["key"]: model for model in model_catalog()}
|
||||
|
||||
self._draw_section(layout, "Environment")
|
||||
layout.prop(self, "storage_root")
|
||||
layout.prop(self, "device")
|
||||
layout.prop(self, "upscale_model")
|
||||
layout.prop(self, "upscale_max_output_size")
|
||||
layout.separator(type="LINE")
|
||||
layout.label(text="Mesh Conversion")
|
||||
layout.prop(self, "mesh_depth_model")
|
||||
mesh_depth_model = getattr(self, "mesh_depth_model", DEFAULT_MOGE2_MODEL_KEY)
|
||||
if mesh_depth_model.startswith("MOGE2_"):
|
||||
layout.prop(self, "mesh_resolution_level")
|
||||
else:
|
||||
layout.prop(self, "mesh_process_res_factor")
|
||||
layout.separator()
|
||||
status = ai_status()
|
||||
layout.label(text=f"Environment: {runtime.environment_directory()}")
|
||||
if not status["environment_ready"]:
|
||||
layout.label(text="Environment is not installed", icon="ERROR")
|
||||
@@ -148,30 +155,109 @@ class AnyImagePreferences(bpy.types.AddonPreferences):
|
||||
text=ai_setup_label(status),
|
||||
icon="IMPORT",
|
||||
)
|
||||
layout.separator(type="LINE")
|
||||
layout.label(text="Models")
|
||||
models = model_catalog()
|
||||
for family in ("moge2", "da3", "ben2", "upscale"):
|
||||
for model in models:
|
||||
if model.get("family") == family and (
|
||||
family != "da3" or model.get("enabled")
|
||||
):
|
||||
self._draw_model(layout, model)
|
||||
layout.separator()
|
||||
|
||||
self._draw_section(layout, "Diagnostics")
|
||||
layout.operator(
|
||||
"anyimage.open_server_log",
|
||||
text="Open Server Log",
|
||||
icon="TEXT",
|
||||
)
|
||||
|
||||
def _draw_model(self, layout, model):
|
||||
section = self._draw_panel(layout, "depth_normal", "Depth & Normal")
|
||||
if section is not None:
|
||||
self._draw_depth_normal(
|
||||
section,
|
||||
models,
|
||||
status["environment_ready"],
|
||||
)
|
||||
|
||||
section = self._draw_panel(
|
||||
layout,
|
||||
"remove_background",
|
||||
"Remove Background",
|
||||
)
|
||||
if section is not None:
|
||||
self._draw_model(
|
||||
section,
|
||||
models.get("BEN2_BASE"),
|
||||
status["environment_ready"],
|
||||
)
|
||||
|
||||
section = self._draw_panel(layout, "upscale", "Upscale")
|
||||
if section is not None:
|
||||
self._draw_upscale(
|
||||
section,
|
||||
models,
|
||||
status["environment_ready"],
|
||||
)
|
||||
|
||||
section = self._draw_panel(layout, "cutout", "Cutout")
|
||||
if section is not None:
|
||||
section.prop(self, "balloon_profile_algorithm")
|
||||
|
||||
def _draw_depth_normal(self, layout, models, environment_ready):
|
||||
layout.prop(self, "mesh_depth_model")
|
||||
mesh_depth_model = getattr(
|
||||
self, "mesh_depth_model", DEFAULT_MOGE2_MODEL_KEY
|
||||
)
|
||||
if mesh_depth_model not in models:
|
||||
mesh_depth_model = DEFAULT_MOGE2_MODEL_KEY
|
||||
self._draw_model(
|
||||
layout,
|
||||
models.get(mesh_depth_model),
|
||||
environment_ready,
|
||||
)
|
||||
if mesh_depth_model.startswith("MOGE2_"):
|
||||
layout.prop(self, "mesh_resolution_level")
|
||||
else:
|
||||
layout.prop(self, "mesh_process_res_factor")
|
||||
layout.label(
|
||||
text="DA3 models cannot generate normals",
|
||||
icon="INFO",
|
||||
)
|
||||
|
||||
def _draw_upscale(self, layout, models, environment_ready):
|
||||
layout.prop(self, "upscale_model")
|
||||
upscale_model = getattr(
|
||||
self, "upscale_model", DEFAULT_UPSCALE_MODEL_KEY
|
||||
)
|
||||
if upscale_model not in models:
|
||||
upscale_model = DEFAULT_UPSCALE_MODEL_KEY
|
||||
self._draw_model(
|
||||
layout,
|
||||
models.get(upscale_model),
|
||||
environment_ready,
|
||||
)
|
||||
layout.prop(self, "upscale_max_output_size")
|
||||
|
||||
@staticmethod
|
||||
def _draw_section(layout, label):
|
||||
layout.separator(type="LINE")
|
||||
layout.label(text=label)
|
||||
|
||||
@staticmethod
|
||||
def _draw_panel(layout, panel_id, label):
|
||||
header, body = layout.panel(
|
||||
f"anyimage_preferences_{panel_id}",
|
||||
default_closed=False,
|
||||
)
|
||||
header.label(text=label)
|
||||
return body
|
||||
|
||||
def _draw_model(self, layout, model, environment_ready=True):
|
||||
from .runtime import runtime
|
||||
|
||||
if model is None:
|
||||
layout.label(text="Model is unavailable", icon="ERROR")
|
||||
return
|
||||
row = layout.row(align=True)
|
||||
row.label(text=model["label"])
|
||||
if model.get("ready"):
|
||||
row.label(text="Ready", icon="CHECKMARK")
|
||||
return
|
||||
if not environment_ready:
|
||||
row.label(text="Install Environment First", icon="INFO")
|
||||
return
|
||||
download_row = row.row(align=True)
|
||||
download_row.enabled = not runtime.server_busy()
|
||||
operator = download_row.operator(
|
||||
|
||||
Reference in New Issue
Block a user