Eliminar el fondo de la imagen C#

En la creación y manipulación de contenidos digitales, eliminar el fondo de las imágenes es una tarea común y esencial. Ya sea que estés trabajando en diseño gráfico, comercio electrónico o cualquier otro proyecto visual, tener la capacidad de aislar objetos de sus fondos amplía tu creatividad. En esta publicación de blog, exploraremos cómo eliminar el fondo de las imágenes mediante programación en C#.

Biblioteca C# para eliminar el fondo de las imágenes

Para eliminar el fondo de las imágenes, usaremos Aspose.Imaging for .NET, una potente biblioteca que proporciona una amplia gama de funciones de procesamiento de imágenes para aplicaciones .NET. Admite varios formatos de imagen y permite a los desarrolladores realizar operaciones como cambiar el tamaño, recortar, rotar y, por supuesto, eliminar fondos con facilidad.

Puede descargar la API o instalarla desde NuGet.

PM> Install-Package Aspose.Imaging

Eliminar el fondo de la imagen con enmascaramiento automático en C#

Para obtener mejores resultados en la eliminación del fondo, se prefiere el método de enmascaramiento automático. El objetivo es crear una máscara que identifique con precisión los píxeles que pertenecen al primer plano y los que pertenecen al fondo. Aspose.Imaging proporciona tres técnicas de enmascaramiento automático para eliminar el fondo de la imagen, como se describe en las siguientes secciones.

Enmascaramiento automático de corte de gráfico con difuminado

En esta técnica, la API realiza un enmascaramiento de imágenes con difuminado según el tamaño de la imagen y utiliza trazos predeterminados calculados automáticamente. El siguiente fragmento de código muestra cómo utilizar el enmascaramiento automático de corte de gráficos con difuminado. La propiedad Args de AutoMaskingGraphCutOptions se puede omitir ya que los trazos predeterminados se colocan allí al 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 utilizar Graph Cut con trazos calculados automáticamente, se utiliza AutoMaskingGraphCutOptions.
    AutoMaskingGraphCutOptions options = new AutoMaskingGraphCutOptions
    {
        // Indicando que se debe realizar un nuevo cálculo de los trazos predeterminados durante la descomposición de la imagen.
        CalculateDefaultStrokes = true,
        // Configuración del radio de desvanecimiento posterior al proceso según el tamaño de la imagen.
        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");

La siguiente captura de pantalla muestra las imágenes de entrada y salida.

eliminar el fondo de la imagen en C#

Reutilización de trazos predeterminados en enmascaramiento automático repetido

En esta técnica, el enmascaramiento de la imagen se realiza mediante trazos predeterminados calculados automáticamente; sin embargo, la API reutiliza las opciones de enmascaramiento para la nueva iteración de enmascaramiento. En el siguiente fragmento de código, puede observar que los datos de los dos objetos supuestos también se especifican en la propiedad AssumedObjects de AutoMaskingGraphCutOptions. Después de los resultados iniciales del enmascaramiento, se realizan ajustes en los trazos de fondo/primer plano aplicados y se lleva a cabo una iteración posterior del enmascaramiento.

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 mejorar los resultados del enmascaramiento, se podrían proporcionar datos de los objetos específicos que deberían incluirse en el resultado del enmascaramiento de primer plano.
List<AssumedObjectData> assumedObjects = new List<AssumedObjectData>();
// Se debe especificar el tipo de objeto y el área que contiene ese objeto.
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 utilizar Graph Cut con trazos calculados automáticamente, se utiliza AutoMaskingGraphCutOptions.
    options = new AutoMaskingGraphCutOptions
    {
        AssumedObjects = assumedObjects,
        // Indicando que se debe realizar un nuevo cálculo de los trazos predeterminados durante la descomposición de la imagen.
        CalculateDefaultStrokes = true,
        // Configuración del radio de desvanecimiento posterior al proceso según el tamaño de la imagen.
        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();

        // Guardando el resultado de enmascaramiento intermedio.
        using (RasterImage resultImage = results[1].GetImage())
        {
            resultImage.Save(dataDir + "result2.png",
                new PngOptions() { ColorType = PngColorType.TruecolorWithAlpha });
        }

        // En este punto, los trazos aplicados de primer plano/fondo se pueden analizar y, en base a ellos, 
        // Los trazos de primer plano/fondo se pueden proporcionar manualmente.
        appliedBackgroundStrokes = options.DefaultBackgroundStrokes;
        appliedForegroundStrokes = options.DefaultForegroundStrokes;
        appliedObjectRectangles = options.DefaultObjectsRectangles;

        // Al reutilizar AutoMaskingGraphCutOptions, no es necesario realizar cálculos de trazo predeterminados por segunda vez.
        // Cuando se proporcionan trazos predeterminados y ObjectsPoints en la propiedad Args de AutoMaskingArgs, las matrices de puntos terminan combinadas.
        // La primera matriz ObjectsPoints se considera una matriz de puntos de fondo y 
        // la segunda matriz ObjectsPoints se considera una matriz de puntos de primer plano.
        // Cuando se proporcionan DefaultObjectsRectangles y ObjectsRectangles en la propiedad Args de AutoMaskingArgs, 
        // solo se utiliza la matriz de Args.
        AutoMaskingArgs newAutoMaskingArgs = new AutoMaskingArgs()
        {
            ObjectsPoints = new Point[][]
            {
                // Además, especificamos las áreas que queremos que se eliminen.
                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 });
        }
    }
}
//Ejemplos: gráfico, corte, repetido, enmascaramiento, con nuevos puntos.cs
// Para mejorar los resultados del enmascaramiento, se podrían proporcionar datos de los objetos específicos que deberían incluirse en el resultado del enmascaramiento de primer plano.
assumedObjects = new List<AssumedObjectData>();
// Se debe especificar el tipo de objeto y el área que contiene ese objeto.
assumedObjects.Add(new AssumedObjectData(DetectedObjectType.Human, new Rectangle(100, 100, 150, 300)));

// La primera iteración de enmascaramiento se realiza para obtener pinceladas de primer plano y fondo calculadas automáticamente.
using (RasterImage image = (RasterImage)Image.Load(dataDir + "couple.jpg"))
{
    // Para utilizar Graph Cut con trazos calculados automáticamente, se utiliza AutoMaskingGraphCutOptions.
    options = new AutoMaskingGraphCutOptions
    {
        AssumedObjects = assumedObjects,
        // Indicando que se debe realizar un nuevo cálculo de los trazos predeterminados durante la descomposición de la imagen.
        CalculateDefaultStrokes = true,
        // Configuración del radio de desvanecimiento posterior al proceso.
        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);

    // En este punto, los trazos aplicados de primer plano/fondo se pueden analizar y, en base a ellos, 
    // Los trazos de primer plano/fondo se pueden proporcionar 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 });
    }
}



// La segunda iteración del enmascaramiento se realiza para mejorar aún más la calidad del enmascaramiento agregando nuevos puntos de primer plano/fondo elegidos manualmente.
using (RasterImage image = (RasterImage)Image.Load(dataDir + "couple.jpg"))
{
    // Al reutilizar AutoMaskingGraphCutOptions, no es necesario realizar cálculos de trazo predeterminados por segunda vez.
    options.CalculateDefaultStrokes = false;
    // Cuando se proporcionan trazos predeterminados y ObjectsPoints en la propiedad Args de AutoMaskingArgs, las matrices de puntos terminan combinadas.
    // La primera matriz ObjectsPoints se considera una matriz de puntos de fondo y 
    // la segunda matriz ObjectsPoints se considera una matriz de puntos de primer plano.
    // Cuando se proporcionan DefaultObjectsRectangles y ObjectsRectangles en la propiedad Args de AutoMaskingArgs, 
    // solo se utiliza la matriz de Args.
    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);

    // Guardando el resultado final del enmascaramiento.
    using (RasterImage resultImage = (RasterImage)results[1].GetImage())
    {
        resultImage.Save(dataDir + "result6.png", new PngOptions() { ColorType = PngColorType.TruecolorWithAlpha });
    }
}



///<summary>
/// Devuelve todos los puntos que pertenecen a los rectángulos especificados.
///</summary>
///<param name="rectangles"> La matriz de rectángulos.</param>
///<returns> Todos los puntos del rectá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");

La siguiente captura de pantalla muestra las imágenes de entrada y salida.

Enmascaramiento automático repetido para eliminar el fondo

Enmascaramiento automático de corte de gráfico con datos de objeto asumidos especificados

En esta técnica, los datos de un objeto supuesto específico se utilizan en la propiedad AssumedObjects de AutoMaskingGraphCutOptions, que se utiliza en iteraciones de enmascaramiento posteriores. El siguiente fragmento de código muestra cómo utilizar el enmascaramiento automático de corte de gráfico con un objeto supuesto para eliminar el fondo de una imagen.

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 mejorar los resultados del enmascaramiento, se podrían proporcionar datos de los objetos específicos que deberían incluirse en el resultado del enmascaramiento de primer plano.
List<AssumedObjectData> assumedObjects = new List<AssumedObjectData>();
// Se debe especificar el tipo de objeto y el área que contiene ese objeto.
assumedObjects.Add(new AssumedObjectData(DetectedObjectType.Human, new Rectangle(0, 0, 256, 365)));

MaskingResult results;
using (RasterImage image = (RasterImage)Image.Load(dataDir + "couple.jpg"))
{
    // Para utilizar Graph Cut con trazos calculados automáticamente, se utiliza AutoMaskingGraphCutOptions.
    AutoMaskingGraphCutOptions options = new AutoMaskingGraphCutOptions
    {
        AssumedObjects = assumedObjects,
        // Indicando que se debe realizar un nuevo cálculo de los trazos predeterminados durante la descomposición de la imagen.
        CalculateDefaultStrokes = true,
        // Configuración del radio de desvanecimiento posterior al proceso según el tamaño de la imagen.
        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);

    // Guardando el resultado final del enmascaramiento.
    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");

La siguiente captura de pantalla muestra las imágenes de entrada y salida.

Enmascaramiento automático de corte de gráfico con objeto asumido

Eliminación del fondo de la imagen mediante enmascaramiento manual

Si no está interesado en el enmascaramiento automático, puede utilizar el método de enmascaramiento manual para eliminar el fondo de las imágenes. El siguiente fragmento de código muestra cómo aplicar enmascaramiento manual a una imagen rasterizada para eliminar su fondo.

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);
    // Guardando el resultado final del enmascaramiento.
    using (RasterImage resultImage = (RasterImage)results[1].GetImage())
    {
        resultImage.Save(dataDir + "result.png", new PngOptions() { ColorType = PngColorType.TruecolorWithAlpha });
    }
}       

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

La siguiente captura de pantalla muestra las imágenes de entrada y salida.

Enmascaramiento manual para eliminación de fondo

Obtenga la API de eliminación de fondo de imagen de C#

Puede obtener una licencia temporal gratuita y utilizar nuestra biblioteca de edición de imágenes y eliminación de fondos sin ninguna limitación.

Conclusión

Eliminar fondos de las imágenes es una habilidad crucial en la edición y el diseño de imágenes. Aspose.Imaging for .NET permite a los desarrolladores eliminar con precisión fondos de imágenes en aplicaciones C#. Esta publicación de blog cubrió los conceptos básicos de cargar imágenes, implementar la eliminación de fondo utilizando diferentes métodos de enmascaramiento automático y manual y guardar la imagen de salida.

Al integrar Aspose.Imaging en sus proyectos de C#, puede optimizar el flujo de trabajo de procesamiento de imágenes y desbloquear un nuevo nivel de creatividad en sus aplicaciones. Experimente con diferentes funciones y técnicas para descubrir todo el potencial de Aspose.Imaging for .NET. Además, comparte tus consultas con nosotros a través de nuestro foro.

Ver también