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

Під час створення та обробки цифрового вмісту видалення фону із зображень є поширеним і важливим завданням. Незалежно від того, чи працюєте ви над графічним дизайном, електронною комерцією чи будь-яким іншим візуальним проектом, можливість ізолювати об’єкти від їхнього фону розширить вашу творчість. У цій публікації блогу ми розглянемо, як програмно видалити фон із зображень у C#.

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

Щоб видалити фон із зображень, ми будемо використовувати Aspose.Imaging for .NET - потужну бібліотеку, яка надає широкий спектр функцій обробки зображень для програм .NET. Він підтримує різні формати зображень і дозволяє розробникам легко виконувати такі операції, як зміна розміру, обрізання, обертання та, звичайно, видалення фону.

Ви можете завантажити API або встановити його з NuGet.

PM> Install-Package Aspose.Imaging

Видалення фону зображення за допомогою автоматичного маскування в C#

Щоб отримати кращі результати видалення фону, краще використовувати метод автоматичного маскування. Мета полягає в тому, щоб створити маску, яка точно ідентифікує пікселі, що належать до переднього плану, і ті, що належать до фону. Aspose.Imaging пропонує три техніки автоматичного маскування для видалення фону із зображення, як описано в наступних розділах.

Автоматичне маскування графічного вирізання з розтушовуванням

У цій техніці 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 вважається масивом точок переднього плану.
        // Якщо надано і DefaultObjectsRectangles, і ObjectsRectangles у властивості Args AutoMaskingArgs, 
        // використовується лише масив із 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 });
        }
    }
}
//Приклади - graph - cut - repeated - masking - with - 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 вважається масивом точок переднього плану.
    // Якщо надано і DefaultObjectsRectangles, і ObjectsRectangles у властивості Args AutoMaskingArgs, 
    // використовується лише масив із 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");

На наступному знімку екрана показано вхідні та вихідні зображення.

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

Отримайте C# Image Background Remover API

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

Висновок

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

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

Дивись також