feat(selection): separate selection geometry from image content processing
- Introduced a new design for selection rasterization that decouples the selection geometry from the image content, ensuring that the SelectionMask is independent of the source image's alpha and color. - Updated the `rasterize_selection_path` function to only accept selection paths and image dimensions, removing parameters related to source alpha and alpha thresholds. - Implemented a new approach for handling selection paths using non-zero winding fill, ensuring overlapping areas are preserved. - Enhanced performance by utilizing a scanline algorithm for rasterization, significantly reducing processing time for high-resolution images. - Updated internal documentation and added comprehensive tests to validate the new behavior and performance improvements. - Ensured backward compatibility by maintaining existing interfaces where necessary while introducing breaking changes in the selection processing logic.
This commit is contained in:
@@ -202,10 +202,10 @@ def _resize_values(values, size):
|
||||
)
|
||||
|
||||
|
||||
def extract_selection_contours(selection_mask, max_resolution=512, threshold=0.5):
|
||||
def extract_selection_contours(selection_values, max_resolution=512, threshold=0.5):
|
||||
import numpy as np
|
||||
|
||||
values = np.asarray(selection_mask.values)
|
||||
values = np.asarray(selection_values)
|
||||
if values.ndim != 2:
|
||||
raise ValueError("Cutout Alpha must be two-dimensional")
|
||||
if np.issubdtype(values.dtype, np.floating):
|
||||
@@ -1341,13 +1341,13 @@ def crop_plane_bounds(source_object, crop_bounds, source_size):
|
||||
|
||||
|
||||
def extract_cutout_contours(
|
||||
selection_mask,
|
||||
content_values,
|
||||
mesh_resolution,
|
||||
threshold=CUTOUT_ALPHA_THRESHOLD,
|
||||
):
|
||||
contour_resolution = max(512, min(int(mesh_resolution) * 8, 1024))
|
||||
return extract_selection_contours(
|
||||
selection_mask,
|
||||
content_values,
|
||||
max_resolution=contour_resolution,
|
||||
threshold=threshold,
|
||||
)
|
||||
@@ -1373,11 +1373,11 @@ def cutout_sampling_spacing(source_object, mesh_resolution):
|
||||
return max(width, height) / max(int(mesh_resolution), 8)
|
||||
|
||||
|
||||
def selection_calibration(selection_mask, target_shape, threshold=CUTOUT_ALPHA_THRESHOLD):
|
||||
"""Return the final Selection mask and transparency ratio at geometry resolution."""
|
||||
def selection_calibration(content_values, target_shape, threshold=CUTOUT_ALPHA_THRESHOLD):
|
||||
"""Return Cutout validity and transparency ratio at geometry resolution."""
|
||||
import numpy as np
|
||||
|
||||
values = np.asarray(selection_mask.values, dtype=np.float32)
|
||||
values = np.asarray(content_values, dtype=np.float32)
|
||||
target_height, target_width = (int(value) for value in target_shape)
|
||||
source_height, source_width = values.shape
|
||||
y = np.minimum(
|
||||
@@ -1394,16 +1394,22 @@ def selection_calibration(selection_mask, target_shape, threshold=CUTOUT_ALPHA_T
|
||||
return valid, transparent_fraction
|
||||
|
||||
|
||||
def build_base_shape(context, source_object, mesh_resolution, selection_mask):
|
||||
def build_base_shape(
|
||||
context,
|
||||
source_object,
|
||||
mesh_resolution,
|
||||
content_values,
|
||||
content_bounds,
|
||||
):
|
||||
import numpy as np
|
||||
|
||||
bounds = crop_plane_bounds(
|
||||
source_object,
|
||||
selection_mask.bounds,
|
||||
content_bounds,
|
||||
tuple(source_object.data.size),
|
||||
)
|
||||
selection_contours = extract_cutout_contours(
|
||||
selection_mask,
|
||||
content_values,
|
||||
mesh_resolution,
|
||||
threshold=CUTOUT_ALPHA_THRESHOLD,
|
||||
)
|
||||
|
||||
Reference in New Issue
Block a user