Удалить фоновое изображение C#

При создании и манипулировании цифровым контентом удаление фона из изображений является распространенной и важной задачей. Независимо от того, работаете ли вы над графическим дизайном, электронной коммерцией или любым другим визуальным проектом, возможность изолировать объекты от их фона расширяет ваши творческие способности. В этой записи блога мы рассмотрим, как программно удалить фон из изображений на C#.

Библиотека C# для удаления фона из изображений

Для удаления фона с изображений мы будем использовать Aspose.Imaging for .NET — мощную библиотеку, предоставляющую широкий набор функций обработки изображений для .NET-приложений. Он поддерживает различные форматы изображений и позволяет разработчикам с легкостью выполнять такие операции, как изменение размера, обрезка, поворот и, конечно же, удаление фона.

Вы можете либо скачать API, либо установить его из NuGet.

PM> Install-Package Aspose.Imaging

Удаление фона изображения с помощью автоматической маскировки в C#

Чтобы получить лучшие результаты удаления фона, предпочтительным является метод автоматической маскировки. Цель состоит в том, чтобы создать маску, которая точно идентифицирует пиксели, принадлежащие переднему плану, и пиксели, принадлежащие фоновому. Aspose.Imaging предоставляет три метода автоматической маскировки для удаления фона из изображения, как описано в следующих разделах.

Автоматическое маскирование Graph Cut с растушевкой

В этом методе API выполняет маскирование изображения с растушевкой в зависимости от размера изображения и использует автоматически рассчитываемые обводки по умолчанию. В следующем фрагменте кода показано, как использовать автоматическую маскировку выреза графика с растушевкой. Свойство Args объекта AutoMaskingGraphCutOptions можно опустить, поскольку обводки по умолчанию размещаются там в конце.

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"))
{
    // Чтобы использовать Graph Cut с автоматически рассчитанными штрихами, используется AutoMaskingGraphCutOptions.
    AutoMaskingGraphCutOptions options = new AutoMaskingGraphCutOptions
    {
        // Указывает на то, что во время декомпозиции изображения следует выполнить новый расчет штрихов по умолчанию.
        CalculateDefaultStrokes = true,
        // Установка радиуса растушевки постобработки в зависимости от размера изображения.
        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");

На следующем снимке экрана показаны входные и выходные изображения.

удаление фона изображения в C#

Повторное использование обводок по умолчанию при повторяющейся автоматической маскировке

В этом методе маскирование изображения выполняется с использованием автоматически рассчитанных штрихов по умолчанию, однако API повторно использует параметры маскировки для новой итерации маскирования. В следующем фрагменте кода вы можете заметить, что данные двух предполагаемых объектов также указаны в свойстве AssumedObjects AutoMaskingGraphCutOptions. После получения первоначальных результатов маскировки вносятся коррективы в примененные штрихи фона/переднего плана и выполняется последующая итерация маскировки.

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;

// Чтобы улучшить результаты маскировки, можно предоставить данные конкретных объектов, которые должны быть включены в результат маскировки переднего плана.
List<AssumedObjectData> assumedObjects = new List<AssumedObjectData>();
// Следует указать тип объекта и область, содержащую этот объект.
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"))
{
    // Чтобы использовать Graph Cut с автоматически рассчитанными штрихами, используется AutoMaskingGraphCutOptions.
    options = new AutoMaskingGraphCutOptions
    {
        AssumedObjects = assumedObjects,
        // Указывает на то, что во время декомпозиции изображения следует выполнить новый расчет штрихов по умолчанию.
        CalculateDefaultStrokes = true,
        // Установка радиуса растушевки постобработки в зависимости от размера изображения.
        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();

        // Сохранение промежуточного результата маскировки.
        using (RasterImage resultImage = results[1].GetImage())
        {
            resultImage.Save(dataDir + "result2.png",
                new PngOptions() { ColorType = PngColorType.TruecolorWithAlpha });
        }

        // На этом этапе можно проанализировать примененные штрихи переднего/фонового плана и на их основе выполнить дополнительные 
        // штрихи переднего плана/фона могут быть предоставлены вручную.
        appliedBackgroundStrokes = options.DefaultBackgroundStrokes;
        appliedForegroundStrokes = options.DefaultForegroundStrokes;
        appliedObjectRectangles = options.DefaultObjectsRectangles;

        // При повторном использовании AutoMaskingGraphCutOptions нет необходимости повторно выполнять вычисления обводки по умолчанию.
        // Если в свойстве Args AutoMaskingArgs указаны как штрихи по умолчанию, так и ObjectsPoints, массивы Point в конечном итоге объединяются.
        // Первый массив ObjectsPoints считается массивом фоновых точек и 
        // второй массив ObjectsPoints считается массивом точек переднего плана.
        // Если в свойстве Args AutoMaskingArgs указаны как DefaultObjectsRectangles, так и ObjectsRectangles, 
        // используется только массив из Args.
        AutoMaskingArgs newAutoMaskingArgs = new AutoMaskingArgs()
        {
            ObjectsPoints = new Point[][]
            {
                // Дополнительно указывая области, которые мы хотим удалить.
                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 });
        }
    }
}
//Примеры - график - вырезание - повторение - маскирование - с - new-points.cs
// Чтобы улучшить результаты маскировки, можно предоставить данные конкретных объектов, которые должны быть включены в результат маскировки переднего плана.
assumedObjects = new List<AssumedObjectData>();
// Следует указать тип объекта и область, содержащую этот объект.
assumedObjects.Add(new AssumedObjectData(DetectedObjectType.Human, new Rectangle(100, 100, 150, 300)));

// Первая итерация маскировки выполняется для получения автоматически рассчитанных мазков переднего/фонового плана.
using (RasterImage image = (RasterImage)Image.Load(dataDir + "couple.jpg"))
{
    // Чтобы использовать Graph Cut с автоматически рассчитанными штрихами, используется AutoMaskingGraphCutOptions.
    options = new AutoMaskingGraphCutOptions
    {
        AssumedObjects = assumedObjects,
        // Указывает на то, что во время декомпозиции изображения следует выполнить новый расчет штрихов по умолчанию.
        CalculateDefaultStrokes = true,
        // Установка радиуса растушевки постобработки.
        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);

    // На этом этапе можно проанализировать примененные штрихи переднего/фонового плана и на их основе выполнить дополнительные 
    // штрихи переднего плана/фона могут быть предоставлены вручную.
    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 });
    }
}



// Вторая итерация маскировки выполняется для дальнейшего улучшения качества маскировки путем добавления новых выбранных вручную точек переднего плана/фона.
using (RasterImage image = (RasterImage)Image.Load(dataDir + "couple.jpg"))
{
    // При повторном использовании AutoMaskingGraphCutOptions нет необходимости повторно выполнять вычисления обводки по умолчанию.
    options.CalculateDefaultStrokes = false;
    // Если в свойстве Args AutoMaskingArgs указаны как штрихи по умолчанию, так и ObjectsPoints, массивы Point в конечном итоге объединяются.
    // Первый массив ObjectsPoints считается массивом фоновых точек и 
    // второй массив ObjectsPoints считается массивом точек переднего плана.
    // Если в свойстве Args AutoMaskingArgs указаны как DefaultObjectsRectangles, так и ObjectsRectangles, 
    // используется только массив из 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);

    // Сохранение окончательного результата маскировки.
    using (RasterImage resultImage = (RasterImage)results[1].GetImage())
    {
        resultImage.Save(dataDir + "result6.png", new PngOptions() { ColorType = PngColorType.TruecolorWithAlpha });
    }
}



///<summary>
/// Возвращаем все точки, принадлежащие указанным прямоугольникам.
///</summary>
///<param name="rectangles"> Массив прямоугольников.</param>
///<returns> Все точки прямоугольника.</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");

На следующем снимке экрана показаны входные и выходные изображения.

Повторное автоматическое маскирование для удаления фона

Автоматическое маскирование вырезания графика с указанными предполагаемыми данными объекта

В этом методе данные конкретного предполагаемого объекта используются в свойстве AssumedObjects AutoMaskingGraphCutOptions, которое используется в последующих итерациях маскирования. В следующем фрагменте кода показано, как использовать автоматическое маскирование вырезания графика с одним предполагаемым объектом для удаления фона изображения.

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;

// Чтобы улучшить результаты маскировки, можно предоставить данные конкретных объектов, которые должны быть включены в результат маскировки переднего плана.
List<AssumedObjectData> assumedObjects = new List<AssumedObjectData>();
// Следует указать тип объекта и область, содержащую этот объект.
assumedObjects.Add(new AssumedObjectData(DetectedObjectType.Human, new Rectangle(0, 0, 256, 365)));

MaskingResult results;
using (RasterImage image = (RasterImage)Image.Load(dataDir + "couple.jpg"))
{
    // Чтобы использовать Graph Cut с автоматически рассчитанными штрихами, используется AutoMaskingGraphCutOptions.
    AutoMaskingGraphCutOptions options = new AutoMaskingGraphCutOptions
    {
        AssumedObjects = assumedObjects,
        // Указывает на то, что во время декомпозиции изображения следует выполнить новый расчет штрихов по умолчанию.
        CalculateDefaultStrokes = true,
        // Установка радиуса растушевки постобработки в зависимости от размера изображения.
        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");

На следующем снимке экрана показаны входные и выходные изображения.

Автоматическое маскирование разреза графика с предполагаемым объектом

Удаление фона изображения с помощью маскировки вручную

Если вас не интересует автоматическая маскировка, вы можете использовать метод ручной маскировки, чтобы удалить фон с изображений. В следующем фрагменте кода показано, как вручную применить маскирование к растровому изображению, чтобы удалить его фон.

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);
    // Сохранение окончательного результата маскировки.
    using (RasterImage resultImage = (RasterImage)results[1].GetImage())
    {
        resultImage.Save(dataDir + "result.png", new PngOptions() { ColorType = PngColorType.TruecolorWithAlpha });
    }
}       

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

На следующем снимке экрана показаны входные и выходные изображения.

Ручное маскирование для удаления фона

Получите API для удаления фона изображения C#

Вы можете получить бесплатную временную лицензию и использовать нашу библиотеку редактирования изображений и удаления фона без каких-либо ограничений.

Заключение

Удаление фона из изображений — важнейший навык в редактировании и дизайне изображений. Aspose.Imaging for .NET позволяет разработчикам точно удалять фон из изображений в приложениях C#. В этом сообщении блога были рассмотрены основы загрузки изображений, реализация удаления фона с использованием различных методов автоматического и ручного маскирования, а также сохранение выходного изображения.

Интегрировав Aspose.Imaging в свои проекты C#, вы сможете оптимизировать рабочий процесс обработки изображений и открыть новый уровень творчества в своих приложениях. Поэкспериментируйте с различными функциями и методами, чтобы раскрыть весь потенциал Aspose.Imaging for .NET. Также поделитесь с нами своими вопросами через наш форум.

Смотрите также