Skip to content

[FEAT]: Better Feathering #2

Closed
Closed

Description

@julianadormon

Hi Steven! Thanks for this project, it really helped me see behind the curtain.

I was getting some unfavourable halos around some of my low res tests. I ended up making more use of the semi-transparency provided by the model on the pixels that transition between foreground to background. Perhaps this can help someone else.

`public async Task RemoveBackgroundAsync(Stream StreamImage, Stream MaskStream)
{
StreamImage.Position = 0;
MaskStream.Position = 0;

        var ImageWithBg = await Image.LoadAsync<Rgba32>(StreamImage);
        var MaskImage = await Image.LoadAsync<Rgba32>(MaskStream);

        using var ImageWithBgRemoved = new Image<Rgba32>(ImageWithBg.Width, ImageWithBg.Height);

        // Define your cutoff range.
        // Values below MinVal become 0 alpha (transparent).
        // Values above MaxVal become 255 alpha (opaque).
        // Anything in between is scaled linearly.
        const byte MinVal = 70;
        const byte MaxVal = 117;

        byte AdjustAlpha(byte MaskValue)
        {
            if (MaskValue <= MinVal)
                return 0;
            if (MaskValue >= MaxVal)
                return 255;

            float Proportion = (MaskValue - MinVal) / (float)(MaxVal - MinVal);
            return (byte)(Proportion * 255f);
        }

        // Walk over every pixel, using the mask’s R channel.
        WalkImage(ImageWithBg.Height, ImageWithBg.Width, (x, y) =>
        {
            var SourcePixel = ImageWithBg[x, y];
            var MaskPixel = MaskImage[x, y];

            // Compute a new alpha value using the linear mapping.
            byte NewAlpha = AdjustAlpha(MaskPixel.R);

            // Construct the new pixel with the same RGB, but replaced alpha.
            ImageWithBgRemoved[x, y] = new Rgba32(SourcePixel.R, SourcePixel.G, SourcePixel.B, NewAlpha);
        });

        var Result = new MemoryStream();
        await ImageWithBgRemoved.SaveAsync(Result, new PngEncoder());
        Result.Position = 0;

        return Result;
    }`

Activity

  1. StevanFreeborn commented on Mar 2, 2025

    @StevanFreeborn
    Owner

    @julianadormon thank you for sharing!

    Definitely agree the edge between the foreground and background is rough.

    I'll experiment with this and see about adding to app like a configurable range passed as options.

  2. changed the title [-]Slightly better feathering.[/-] [+][FEAT]: Better Feathering[/+] on Mar 3, 2025
  3. StevanFreeborn commented on Jul 15, 2026

    @StevanFreeborn
    Owner

    Apologies it took me so long to get back to this feedback. I've been stubbing my toe on it over the last year or so while making thumbnails for my YouTube videos. I think the changes I introduced in #3 will help with this issue. Here is an example of the results on an image I think that demonstrates the issue.

    Test image:

    Image

    Previous version:

    Image

    New version:

    Image
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Labels

enhancementNew feature or request

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions