Remover fundo da imagem C#

Na criação e manipulação de conteúdo digital, remover o fundo das imagens é uma tarefa comum e essencial. Esteja você trabalhando em design gráfico, comércio eletrônico ou qualquer outro projeto visual, ter a capacidade de isolar objetos de seus fundos amplia sua criatividade. Nesta postagem do blog, exploraremos como remover o plano de fundo de imagens programaticamente em C#.

Biblioteca C# para remover fundo de imagens

Para remover o fundo das imagens, usaremos Aspose.Imaging for .NET - uma biblioteca poderosa que fornece uma ampla gama de recursos de processamento de imagens para aplicativos .NET. Ele suporta vários formatos de imagem e permite aos desenvolvedores realizar operações como redimensionar, cortar, girar e, claro, remover fundos com facilidade.

Você pode baixar a API ou instalá-la do NuGet.

PM> Install-Package Aspose.Imaging

Removendo o fundo da imagem com mascaramento automático em C#

Para obter melhores resultados de remoção de fundo, é preferível o método de mascaramento automático. O objetivo é criar uma máscara que identifique com precisão os pixels pertencentes ao primeiro plano e os pertencentes ao fundo. Aspose.Imaging fornece três técnicas de mascaramento automático para remover o fundo da imagem, conforme descrito nas seções a seguir.

Máscara automática de corte de gráfico com difusão

Nesta técnica, a API realiza o mascaramento da imagem com enevoamento com base no tamanho da imagem e usa traços padrão calculados automaticamente. O trecho de código a seguir mostra como usar o mascaramento automático de corte de gráfico com enevoamento. A propriedade Args de AutoMaskingGraphCutOptions pode ser omitida, pois os traços padrão são colocados lá no final.

using Aspose.Imaging;
using Aspose.Imaging.FileFormats.Png;
using Aspose.Imaging.ImageOptions;
using Aspose.Imaging.Masking;
using Aspose.Imaging.Masking.Options;
using Aspose.Imaging.Masking.Result;
using Aspose.Imaging.Sources;
using System;
using System.IO;

string templatesFolder = @"c:\Users\USER\Downloads\templates\";
string dataDir = templatesFolder;

MaskingResult results;
using (RasterImage image = (RasterImage)Image.Load(dataDir + "couple.jpg"))
{
    // Para usar Graph Cut com traços calculados automaticamente, AutoMaskingGraphCutOptions é usado.
    AutoMaskingGraphCutOptions options = new AutoMaskingGraphCutOptions
    {
        // Indicando que um novo cálculo dos traços padrão deverá ser realizado durante a decomposição da imagem.
        CalculateDefaultStrokes = true,
        // Definir o raio de enevoamento pós-processamento com base no tamanho da imagem.
        FeatheringRadius = (Math.Max(image.Width, image.Height) / 500) + 1,
        Method = SegmentationMethod.GraphCut,
        Decompose = false,
        ExportOptions =
                                                        new PngOptions()
                                                        {
                                                            ColorType = PngColorType.TruecolorWithAlpha,
                                                            Source = new FileCreateSource(dataDir + "result.png")
                                                        },
        BackgroundReplacementColor = Color.Transparent
    };

    results = new ImageMasking(image).Decompose(options);

    using (RasterImage resultImage = (RasterImage)results[1].GetImage())
    {
        resultImage.Save(dataDir + "result2.png", new PngOptions() { ColorType = PngColorType.TruecolorWithAlpha });
    }
}



File.Delete(dataDir + "result.png");
File.Delete(dataDir + "result2.png");

A captura de tela a seguir mostra as imagens de entrada e saída.

removendo o fundo da imagem em C#

Reutilizando traços padrão em mascaramento automático repetido

Nesta técnica, o mascaramento da imagem é feito usando traços padrão calculados automaticamente; no entanto, a API reutiliza as opções de mascaramento para a nova iteração de mascaramento. No trecho de código a seguir, você pode notar que os dados dos dois objetos assumidos também são especificados na propriedade AssumedObjects do AutoMaskingGraphCutOptions. Após os resultados iniciais do mascaramento, são feitos ajustes nos traços de fundo/primeiro plano aplicados e uma iteração subsequente do mascaramento é realizada.

using Aspose.Imaging;
using Aspose.Imaging.FileFormats.Png;
using Aspose.Imaging.ImageOptions;
using Aspose.Imaging.Masking;
using Aspose.Imaging.Masking.Options;
using Aspose.Imaging.Masking.Result;
using Aspose.Imaging.Sources;
using System;
using System.Collections.Generic;
using System.IO;

string templatesFolder = @"c:\Users\USER\Downloads\templates\";
string dataDir = templatesFolder;

// Para melhorar os resultados do mascaramento, podem ser fornecidos dados dos objetos específicos que devem ser incluídos no resultado do mascaramento de primeiro plano.
List<AssumedObjectData> assumedObjects = new List<AssumedObjectData>();
// O tipo de objeto e a área que contém esse objeto devem ser especificados.
assumedObjects.Add(new AssumedObjectData(DetectedObjectType.Human, new Rectangle(0, 0, 300, 300)));

MaskingResult results;
AutoMaskingGraphCutOptions options;
Point[] appliedBackgroundStrokes;
Point[] appliedForegroundStrokes;
Rectangle[] appliedObjectRectangles;

using (RasterImage image = (RasterImage)Image.Load(dataDir + "couple.jpg"))
{
    // Para usar Graph Cut com traços calculados automaticamente, AutoMaskingGraphCutOptions é usado.
    options = new AutoMaskingGraphCutOptions
    {
        AssumedObjects = assumedObjects,
        // Indicando que um novo cálculo dos traços padrão deverá ser realizado durante a decomposição da imagem.
        CalculateDefaultStrokes = true,
        // Definir o raio de enevoamento pós-processamento com base no tamanho da imagem.
        FeatheringRadius = (Math.Max(image.Width, image.Height) / 500) + 1,
        Method = SegmentationMethod.GraphCut,
        Decompose = false,
        ExportOptions = new PngOptions()
        {
            ColorType = PngColorType.TruecolorWithAlpha,
            Source = new FileCreateSource(dataDir + "result.png")
        },
        BackgroundReplacementColor = Color.Transparent
    };

    using (IMaskingSession maskingSession = new ImageMasking(image).CreateSession(options))
    {
        results = maskingSession.Decompose();

        // Salvando o resultado de mascaramento intermediário.
        using (RasterImage resultImage = results[1].GetImage())
        {
            resultImage.Save(dataDir + "result2.png",
                new PngOptions() { ColorType = PngColorType.TruecolorWithAlpha });
        }

        // Neste ponto, os traços aplicados de primeiro plano/fundo podem ser analisados e, com base neles, 
        // os traços de primeiro plano/fundo podem ser fornecidos manualmente.
        appliedBackgroundStrokes = options.DefaultBackgroundStrokes;
        appliedForegroundStrokes = options.DefaultForegroundStrokes;
        appliedObjectRectangles = options.DefaultObjectsRectangles;

        // Reutilizando AutoMaskingGraphCutOptions, não há necessidade de realizar cálculos de traçado padrão uma segunda vez.
        // Quando os traços padrão e ObjectsPoints na propriedade Args de AutoMaskingArgs são fornecidos, as matrizes de pontos são combinadas.
        // O primeiro array ObjectsPoints é considerado um array de pontos de fundo e 
        // a segunda matriz ObjectsPoints é considerada uma matriz de pontos de primeiro plano.
        // Quando DefaultObjectsRectangles e ObjectsRectangles na propriedade Args de AutoMaskingArgs são fornecidos, 
        // apenas o array do Args está sendo usado.
        AutoMaskingArgs newAutoMaskingArgs = new AutoMaskingArgs()
        {
            ObjectsPoints = new Point[][]
            {
                // Especificando adicionalmente as áreas que queremos remover.
                GetRectanglePoints(
                    new Rectangle(100, 100, 35, 90),
                    new Rectangle(300, 140, 95, 50)
                )
            },
        };

        results = maskingSession.ImproveDecomposition(newAutoMaskingArgs);

        using (RasterImage resultImage = results[1].GetImage())
        {
            resultImage.Save(dataDir +
                "result3.png",
                new PngOptions() { ColorType = PngColorType.TruecolorWithAlpha });
        }
    }
}
//Exemplos - gráfico - corte - repetido - mascaramento - com - novos pontos.cs
// Para melhorar os resultados do mascaramento, podem ser fornecidos dados dos objetos específicos que devem ser incluídos no resultado do mascaramento de primeiro plano.
assumedObjects = new List<AssumedObjectData>();
// O tipo de objeto e a área que contém esse objeto devem ser especificados.
assumedObjects.Add(new AssumedObjectData(DetectedObjectType.Human, new Rectangle(100, 100, 150, 300)));

// A primeira iteração de mascaramento é executada para obter pinceladas de primeiro plano/fundo calculadas automaticamente.
using (RasterImage image = (RasterImage)Image.Load(dataDir + "couple.jpg"))
{
    // Para usar Graph Cut com traços calculados automaticamente, AutoMaskingGraphCutOptions é usado.
    options = new AutoMaskingGraphCutOptions
    {
        AssumedObjects = assumedObjects,
        // Indicando que um novo cálculo dos traços padrão deverá ser realizado durante a decomposição da imagem.
        CalculateDefaultStrokes = true,
        // Configurando o raio de enevoamento pós-processamento.
        FeatheringRadius = 3,
        Method = SegmentationMethod.GraphCut,
        Decompose = false,
        ExportOptions =
                            new PngOptions()
                            {
                                ColorType = PngColorType.TruecolorWithAlpha,
                                Source = new FileCreateSource(dataDir + "result4.png")
                            },
        BackgroundReplacementColor = Color.Transparent
    };

    results = new ImageMasking(image).Decompose(options);

    // Neste ponto, os traços aplicados de primeiro plano/fundo podem ser analisados e, com base neles, 
    // os traços de primeiro plano/fundo podem ser fornecidos manualmente.
    appliedBackgroundStrokes = options.DefaultBackgroundStrokes;
    appliedForegroundStrokes = options.DefaultForegroundStrokes;
    appliedObjectRectangles = options.DefaultObjectsRectangles;
    using (RasterImage resultImage = (RasterImage)results[1].GetImage())
    {
        resultImage.Save(dataDir + "result5.png", new PngOptions() { ColorType = PngColorType.TruecolorWithAlpha });
    }
}



// A segunda iteração de mascaramento é executada para melhorar ainda mais a qualidade do mascaramento, adicionando novos pontos de primeiro plano/fundo escolhidos manualmente.
using (RasterImage image = (RasterImage)Image.Load(dataDir + "couple.jpg"))
{
    // Reutilizando AutoMaskingGraphCutOptions, não há necessidade de realizar cálculos de traçado padrão uma segunda vez.
    options.CalculateDefaultStrokes = false;
    // Quando os traços padrão e ObjectsPoints na propriedade Args de AutoMaskingArgs são fornecidos, as matrizes de pontos são combinadas.
    // O primeiro array ObjectsPoints é considerado um array de pontos de fundo e 
    // a segunda matriz ObjectsPoints é considerada uma matriz de pontos de primeiro plano.
    // Quando DefaultObjectsRectangles e ObjectsRectangles na propriedade Args de AutoMaskingArgs são fornecidos, 
    // apenas o array do Args está sendo usado.
    options.Args = new AutoMaskingArgs()
    {
        ObjectsPoints = new Point[][]
                                                {
                                                    new Point[] { new Point(100, 100), new Point(150, 100) },
                                                    new Point[] { new Point(300, 200) },
                                                },
        ObjectsRectangles = new Rectangle[]
                                                    {
                                                        new Rectangle(100, 100, 300, 300),
                                                    }
    };

    results = new ImageMasking(image).Decompose(options);

    // Salvando o resultado final do mascaramento.
    using (RasterImage resultImage = (RasterImage)results[1].GetImage())
    {
        resultImage.Save(dataDir + "result6.png", new PngOptions() { ColorType = PngColorType.TruecolorWithAlpha });
    }
}



///<summary>
/// Retorna todos os pontos que pertencem aos retângulos especificados.
///</summary>
///<param name="rectangles"> A matriz de retângulos.</param>
///<returns> Todos os pontos do retângulo.</returns>
static Point[] GetRectanglePoints(params Rectangle[] rectangles)
{
    int arraySize = 0;
    foreach (Rectangle rectangle in rectangles)
    {
        arraySize += rectangle.Width * rectangle.Height;
    }

    Point[] pointArray = new Point[arraySize];
    int arrayIndex = 0;
    foreach (Rectangle rectangle in rectangles)
    {
       for (int x = rectangle.Left; x < rectangle.Right; x++)
        {
           for (int y = rectangle.Top; y < rectangle.Bottom; y++)
            {
                pointArray[arrayIndex++] = new Point(x, y);
            }
        }
    }

    return pointArray;
}


File.Delete(dataDir + "result.png");
File.Delete(dataDir + "result2.png");
File.Delete(dataDir + "result3.png");
File.Delete(dataDir + "result4.png");
File.Delete(dataDir + "result5.png");
File.Delete(dataDir + "result6.png");

A captura de tela a seguir mostra as imagens de entrada e saída.

Mascaramento automático repetido para remoção de fundo

Mascaramento automático de corte de gráfico com dados de objeto presumidos especificados

Nesta técnica, os dados de um objeto assumido específico são usados na propriedade AssumedObjects de AutoMaskingGraphCutOptions, que é usada em iterações de mascaramento subsequentes. O trecho de código a seguir mostra como usar o mascaramento automático de corte de gráfico com um objeto assumido para remover o plano de fundo de uma imagem.

using Aspose.Imaging;
using Aspose.Imaging.FileFormats.Png;
using Aspose.Imaging.ImageOptions;
using Aspose.Imaging.Masking;
using Aspose.Imaging.Masking.Options;
using Aspose.Imaging.Masking.Result;
using Aspose.Imaging.Sources;
using System;
using System.Collections.Generic;
using System.IO;

string templatesFolder = @"c:\Users\USER\Downloads\templates\";
string dataDir = templatesFolder;

// Para melhorar os resultados do mascaramento, podem ser fornecidos dados dos objetos específicos que devem ser incluídos no resultado do mascaramento de primeiro plano.
List<AssumedObjectData> assumedObjects = new List<AssumedObjectData>();
// O tipo de objeto e a área que contém esse objeto devem ser especificados.
assumedObjects.Add(new AssumedObjectData(DetectedObjectType.Human, new Rectangle(0, 0, 256, 365)));

MaskingResult results;
using (RasterImage image = (RasterImage)Image.Load(dataDir + "couple.jpg"))
{
    // Para usar Graph Cut com traços calculados automaticamente, AutoMaskingGraphCutOptions é usado.
    AutoMaskingGraphCutOptions options = new AutoMaskingGraphCutOptions
    {
        AssumedObjects = assumedObjects,
        // Indicando que um novo cálculo dos traços padrão deverá ser realizado durante a decomposição da imagem.
        CalculateDefaultStrokes = true,
        // Definir o raio de enevoamento pós-processamento com base no tamanho da imagem.
        FeatheringRadius = (Math.Max(image.Width, image.Height) / 500) + 1,
        Method = SegmentationMethod.GraphCut,
        Decompose = false,
        ExportOptions =
                                                        new PngOptions()
                                                        {
                                                            ColorType = PngColorType.TruecolorWithAlpha,
                                                            Source = new FileCreateSource(dataDir + "result.png")
                                                        },
        BackgroundReplacementColor = Color.Transparent
    };

    results = new ImageMasking(image).Decompose(options);

    // Salvando o resultado final do mascaramento.
    using (RasterImage resultImage = (RasterImage)results[1].GetImage())
    {
        resultImage.Save(dataDir + "result2.png", new PngOptions() { ColorType = PngColorType.TruecolorWithAlpha });
    }
}



File.Delete(dataDir + "result.png");
File.Delete(dataDir + "result2.png");

A captura de tela a seguir mostra as imagens de entrada e saída.

Mascaramento automático de corte de gráfico com objeto presumido

Remoção de fundo de imagem usando máscara manual

Se não estiver interessado no mascaramento automático, você pode usar o método de mascaramento manual para remover o fundo das imagens. O trecho de código a seguir mostra como aplicar mascaramento manual a uma imagem raster para remover seu plano de fundo.

using Aspose.Imaging;
using Aspose.Imaging.FileFormats.Png;
using Aspose.Imaging.ImageOptions;
using Aspose.Imaging.Masking;
using Aspose.Imaging.Masking.Options;
using Aspose.Imaging.Masking.Result;
using Aspose.Imaging.Shapes;
using Aspose.Imaging.Sources;
using System.IO;

string templatesFolder = @"c:\Users\USER\Downloads\templates\";
string dataDir = templatesFolder;

string sourceFileName = dataDir + "couple.png";
GraphicsPath manualMask = new GraphicsPath();
Figure firstFigure = new Figure();
firstFigure.AddShape(new EllipseShape(new RectangleF(100, 30, 40, 40)));
firstFigure.AddShape(new RectangleShape(new RectangleF(10, 200, 50, 30)));
manualMask.AddFigure(firstFigure);
GraphicsPath subPath = new GraphicsPath();
Figure secondFigure = new Figure();
secondFigure.AddShape(
    new PolygonShape(
     new PointF[]
     {
         new PointF(310, 100), new PointF(350, 200), new PointF(250, 200)

     }, true));

secondFigure.AddShape(new PieShape(new RectangleF(10, 10, 80, 80), 30, 120));
subPath.AddFigure(secondFigure);
manualMask.AddPath(subPath);
using (RasterImage image = (RasterImage)Image.Load(sourceFileName))
{
    MaskingOptions maskingOptions = new MaskingOptions()
    {
        Method = SegmentationMethod.Manual,
        Args = new ManualMaskingArgs
        {
            Mask = manualMask
        },
        Decompose = false,
        ExportOptions =
      new PngOptions()
      {
          ColorType = PngColorType.TruecolorWithAlpha,
          Source = new StreamSource(new MemoryStream())
      },
    };
    MaskingResult results = new ImageMasking(image).Decompose(maskingOptions);
    // Salvando o resultado final do mascaramento.
    using (RasterImage resultImage = (RasterImage)results[1].GetImage())
    {
        resultImage.Save(dataDir + "result.png", new PngOptions() { ColorType = PngColorType.TruecolorWithAlpha });
    }
}       

File.Delete(dataDir + "result.png");

A captura de tela a seguir mostra as imagens de entrada e saída.

Mascaramento manual para remoção de fundo

Obtenha API de remoção de fundo de imagem C#

Você pode obter uma licença temporária gratuita e usar nossa biblioteca de edição de imagens e remoção de plano de fundo sem quaisquer limitações.

Conclusão

Remover fundos de imagens é uma habilidade crucial na edição e design de imagens. Aspose.Imaging for .NET permite que os desenvolvedores removam com precisão fundos de imagens em aplicativos C#. Esta postagem do blog abordou os fundamentos do carregamento de imagens, implementação da remoção de fundo usando diferentes métodos de mascaramento automático e manual e salvamento da imagem de saída.

Ao integrar o Aspose.Imaging em seus projetos C#, você pode agilizar o fluxo de trabalho de processamento de imagens e desbloquear um novo nível de criatividade em seus aplicativos. Experimente diferentes recursos e técnicas para descobrir todo o potencial do Aspose.Imaging for .NET. Além disso, compartilhe suas dúvidas conosco através do nosso fórum.

Veja também