Skip to content

fix(nodes): expanded masks not 100% transparent outside the fade out region #7854

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Mar 31, 2025
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 16 additions & 3 deletions invokeai/app/invocations/image.py
Original file line number Diff line number Diff line change
Expand Up @@ -1089,7 +1089,7 @@ def invoke(self, context: InvocationContext) -> ImageOutput:


@invocation(
"expand_mask_with_fade", title="Expand Mask with Fade", tags=["image", "mask"], category="image", version="1.0.0"
"expand_mask_with_fade", title="Expand Mask with Fade", tags=["image", "mask"], category="image", version="1.0.1"
)
class ExpandMaskWithFadeInvocation(BaseInvocation, WithMetadata, WithBoard):
"""Expands a mask with a fade effect. The mask uses black to indicate areas to keep from the generated image and white for areas to discard.
Expand Down Expand Up @@ -1147,8 +1147,21 @@ def invoke(self, context: InvocationContext) -> ImageOutput:
coeffs = numpy.polyfit(x_control, y_control, 3)
poly = numpy.poly1d(coeffs)

# Evaluate and clip the smooth mapping
feather = numpy.clip(poly(d_norm), 0, 1)
# Evaluate the polynomial
feather = poly(d_norm)

# The polynomial fit isn't perfect. Points beyond the fade distance are likely to be slightly less than 1.0,
# even though the control points indicate that they should be exactly 1.0. This is due to the nature of the
# polynomial fit, which is a best approximation of the control points but not an exact match.

# When this occurs, the area outside the mask and fade-out will not be 100% transparent. For example, it may
# have an alpha value of 1 instead of 0. So we must force pixels at or beyond the fade distance to exactly 1.0.

# Force pixels at or beyond the fade distance to exactly 1.0
feather = numpy.where(d_norm >= 1.0, 1.0, feather)

# Clip any other values to ensure they're in the valid range [0,1]
feather = numpy.clip(feather, 0, 1)

# Build final image.
np_result = numpy.where(black_mask == 1, 0, (feather * 255).astype(numpy.uint8))
Expand Down