Refactor Cutout and Image Editing Logic
- Renamed "Base Plane Depth" to "Reference Depth" across validate_cutout.py for consistency. - Introduced a new specification for Cutout mesh sampling to ensure source pixel spacing is preserved and limits are applied correctly. - Unified naming conventions for image editing results to maintain consistency across Remove Background, Upscale, and Crop operations. - Updated the handling of Refine Selection to ensure it retains the original bounds and does not apply unnecessary cropping. - Enhanced material generation logic to connect image color directly to IOR Level, improving the rendering of dark areas. - Established clear requirements for geometry depth controls and image result materials to ensure consistent behavior across different components. - Removed outdated logic and ensured all changes are documented and tested for regression.
This commit is contained in:
@@ -4,7 +4,6 @@ import math
|
||||
from dataclasses import dataclass
|
||||
|
||||
from ...preferences import addon_preferences
|
||||
from ...server.media.resolution import limited_image_size
|
||||
from ...common.image import image_empty_bounds
|
||||
|
||||
|
||||
@@ -1342,10 +1341,12 @@ def crop_plane_bounds(source_object, crop_bounds, source_size):
|
||||
|
||||
def extract_cutout_contours(
|
||||
content_values,
|
||||
mesh_resolution,
|
||||
point_spacing,
|
||||
threshold=CUTOUT_ALPHA_THRESHOLD,
|
||||
):
|
||||
contour_resolution = max(512, min(int(mesh_resolution) * 8, 1024))
|
||||
height, width = content_values.shape
|
||||
sampling_resolution = max(width, height) / float(point_spacing)
|
||||
contour_resolution = max(512, min(round(sampling_resolution * 8), 1024))
|
||||
return extract_selection_contours(
|
||||
content_values,
|
||||
max_resolution=contour_resolution,
|
||||
@@ -1353,24 +1354,28 @@ def extract_cutout_contours(
|
||||
)
|
||||
|
||||
|
||||
def limit_cutout_mesh_resolution(mesh_resolution, crop_size, max_input_size):
|
||||
def limit_cutout_point_spacing(point_spacing, crop_size, max_mesh_resolution):
|
||||
crop_width, crop_height = (int(value) for value in crop_size)
|
||||
limited_width, limited_height = limited_image_size(
|
||||
(crop_width, crop_height),
|
||||
max_input_size,
|
||||
)
|
||||
scale = max(limited_width, limited_height) / max(crop_width, crop_height)
|
||||
return max(4, min(1024, round(int(mesh_resolution) * scale)))
|
||||
spacing = float(point_spacing)
|
||||
if crop_width <= 0 or crop_height <= 0:
|
||||
raise ValueError("The Cutout bounds must be positive")
|
||||
if spacing <= 0.0:
|
||||
raise ValueError("Cutout point spacing must be greater than zero")
|
||||
maximum = int(max_mesh_resolution)
|
||||
if maximum <= 0:
|
||||
raise ValueError("Maximum Cutout mesh resolution must be positive")
|
||||
return max(spacing, max(crop_width, crop_height) / maximum)
|
||||
|
||||
|
||||
def cutout_sampling_spacing(source_object, mesh_resolution):
|
||||
def cutout_sampling_spacing(source_object, point_spacing):
|
||||
import math
|
||||
|
||||
x_min, x_max, y_min, y_max = image_empty_bounds(source_object)
|
||||
metric, _world_z_scale = world_plane_metric(source_object.matrix_world)
|
||||
width = (x_max - x_min) * math.sqrt(max(metric[0][0], 0.0))
|
||||
height = (y_max - y_min) * math.sqrt(max(metric[1][1], 0.0))
|
||||
return max(width, height) / max(int(mesh_resolution), 8)
|
||||
image_width, image_height = (int(value) for value in source_object.data.size)
|
||||
return max(width / image_width, height / image_height) * float(point_spacing)
|
||||
|
||||
|
||||
def selection_calibration(content_values, target_shape, threshold=CUTOUT_ALPHA_THRESHOLD):
|
||||
@@ -1397,7 +1402,7 @@ def selection_calibration(content_values, target_shape, threshold=CUTOUT_ALPHA_T
|
||||
def build_base_shape(
|
||||
context,
|
||||
source_object,
|
||||
mesh_resolution,
|
||||
point_spacing,
|
||||
content_values,
|
||||
content_bounds,
|
||||
):
|
||||
@@ -1410,7 +1415,7 @@ def build_base_shape(
|
||||
)
|
||||
selection_contours = extract_cutout_contours(
|
||||
content_values,
|
||||
mesh_resolution,
|
||||
point_spacing,
|
||||
threshold=CUTOUT_ALPHA_THRESHOLD,
|
||||
)
|
||||
world_metric, world_z_scale = world_plane_metric(source_object.matrix_world)
|
||||
@@ -1418,7 +1423,7 @@ def build_base_shape(
|
||||
raise ValueError("The Image Empty has a degenerate world transform")
|
||||
preferences = addon_preferences(context)
|
||||
balloon_algorithm = getattr(preferences, "balloon_profile_algorithm", "POISSON")
|
||||
point_spacing = cutout_sampling_spacing(source_object, mesh_resolution)
|
||||
point_spacing = cutout_sampling_spacing(source_object, point_spacing)
|
||||
domain = cutout_domain(
|
||||
selection_contours,
|
||||
bounds,
|
||||
|
||||
Reference in New Issue
Block a user