Odebrat pozadí obrázku C#

Při vytváření a manipulaci s digitálním obsahem je odstranění pozadí z obrázků běžným a zásadním úkolem. Ať už pracujete na grafickém designu, e-commerce nebo jakémkoli jiném vizuálním projektu, schopnost izolovat objekty od jejich pozadí rozšiřuje vaši kreativitu. V tomto příspěvku na blogu prozkoumáme, jak odstranit pozadí z obrázků programově v C#.

Knihovna C# pro odstranění pozadí z obrázků

K odstranění pozadí z obrázků použijeme Aspose.Imaging for .NET – výkonnou knihovnu, která poskytuje širokou škálu funkcí pro zpracování obrázků pro aplikace .NET. Podporuje různé formáty obrázků a umožňuje vývojářům snadno provádět operace, jako je změna velikosti, oříznutí, otočení a samozřejmě odstranění pozadí.

API si můžete buď stáhnout, nebo jej nainstalovat z NuGet.

PM> Install-Package Aspose.Imaging

Odstranění pozadí obrázku pomocí automatického maskování v C#

Chcete-li získat lepší výsledky odstraňování pozadí, upřednostňuje se metoda automatického maskování. Cílem je vytvořit masku, která přesně identifikuje pixely patřící do popředí a pixely patřící do pozadí. Aspose.Imaging poskytuje tři techniky automatického maskování pro odstranění pozadí z obrázku, jak je popsáno v následujících částech.

Automatické maskování grafu s prolnutím

V této technice rozhraní API provádí maskování obrazu s prolnutím na základě velikosti obrazu a používá automaticky vypočítané výchozí tahy. Následující fragment kódu ukazuje, jak používat automatické maskování řezu grafu s prolnutím. Vlastnost Args AutoMaskingGraphCutOptions lze vynechat, protože tam jsou nakonec umístěny výchozí tahy.

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"))
{
    // Chcete-li použít Graph Cut s automaticky vypočítanými tahy, použije se AutoMaskingGraphCutOptions.
    AutoMaskingGraphCutOptions options = new AutoMaskingGraphCutOptions
    {
        // Indikuje, že během rozkladu obrazu by měl být proveden nový výpočet výchozích tahů.
        CalculateDefaultStrokes = true,
        // Nastavení poloměru prolnutí po zpracování na základě velikosti obrázku.
        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");

Následující snímek obrazovky ukazuje vstupní a výstupní obrázky.

odstranění pozadí obrázku v C#

Opětovné použití výchozích tahů v opakovaném automatickém maskování

V této technice se maskování obrazu provádí pomocí automaticky vypočítaných výchozích tahů, avšak API znovu používá možnosti maskování pro novou iteraci maskování. V následujícím fragmentu kódu si můžete všimnout, že data dvou předpokládaných objektů jsou také specifikována ve vlastnosti AssumedObjects AutoMaskingGraphCutOptions. Po počátečních výsledcích maskování se provedou úpravy aplikovaných tahů pozadí/popředí a provede se následná iterace maskování.

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;

// Pro zlepšení výsledků maskování by mohla být poskytnuta data konkrétních objektů, které by měly být zahrnuty do výsledku maskování popředí.
List<AssumedObjectData> assumedObjects = new List<AssumedObjectData>();
// Měl by být specifikován typ objektu a oblast obsahující tento objekt.
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"))
{
    // Chcete-li použít Graph Cut s automaticky vypočítanými tahy, použije se AutoMaskingGraphCutOptions.
    options = new AutoMaskingGraphCutOptions
    {
        AssumedObjects = assumedObjects,
        // Indikuje, že během rozkladu obrazu by měl být proveden nový výpočet výchozích tahů.
        CalculateDefaultStrokes = true,
        // Nastavení poloměru prolnutí po zpracování na základě velikosti obrázku.
        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();

        // Ukládání mezivýsledku maskování.
        using (RasterImage resultImage = results[1].GetImage())
        {
            resultImage.Save(dataDir + "result2.png",
                new PngOptions() { ColorType = PngColorType.TruecolorWithAlpha });
        }

        // V tomto bodě mohou být aplikované tahy popředí/pozadí analyzovány a na jejich základě další 
        // tahy popředí/pozadí lze zadat ručně.
        appliedBackgroundStrokes = options.DefaultBackgroundStrokes;
        appliedForegroundStrokes = options.DefaultForegroundStrokes;
        appliedObjectRectangles = options.DefaultObjectsRectangles;

        // Při opětovném použití AutoMaskingGraphCutOptions není nutné provádět výchozí výpočty zdvihu podruhé.
        // Když jsou k dispozici výchozí tahy i ObjectsPoints ve vlastnosti Args AutoMaskingArgs, pole Point se nakonec zkombinují.
        // První pole ObjectsPoints je považováno za pole bodů pozadí a 
        // druhé pole ObjectsPoints je považováno za pole bodů v popředí.
        // Když jsou ve vlastnosti Args AutoMaskingArgs k dispozici jak DefaultObjectsRectangles, tak ObjectsRectangles, 
        // používá se pouze pole z Args.
        AutoMaskingArgs newAutoMaskingArgs = new AutoMaskingArgs()
        {
            ObjectsPoints = new Point[][]
            {
                // Dodatečně specifikující oblasti, které chceme odstranit.
                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 });
        }
    }
}
//Příklady - graf - řez - opakování - maskování - s - nové- body.cs
// Pro zlepšení výsledků maskování by mohla být poskytnuta data konkrétních objektů, které by měly být zahrnuty do výsledku maskování popředí.
assumedObjects = new List<AssumedObjectData>();
// Měl by být specifikován typ objektu a oblast obsahující tento objekt.
assumedObjects.Add(new AssumedObjectData(DetectedObjectType.Human, new Rectangle(100, 100, 150, 300)));

// Provede se první iterace maskování, aby se získaly automaticky vypočítané tahy štětcem popředí/pozadí.
using (RasterImage image = (RasterImage)Image.Load(dataDir + "couple.jpg"))
{
    // Chcete-li použít Graph Cut s automaticky vypočítanými tahy, použije se AutoMaskingGraphCutOptions.
    options = new AutoMaskingGraphCutOptions
    {
        AssumedObjects = assumedObjects,
        // Indikuje, že během rozkladu obrazu by měl být proveden nový výpočet výchozích tahů.
        CalculateDefaultStrokes = true,
        // Nastavení poloměru prolnutí po zpracování.
        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);

    // V tomto bodě mohou být aplikované tahy popředí/pozadí analyzovány a na jejich základě další 
    // tahy popředí/pozadí lze zadat ručně.
    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 });
    }
}



// Druhá iterace maskování se provádí za účelem dalšího zlepšení kvality maskování přidáním nových ručně vybraných bodů popředí/pozadí.
using (RasterImage image = (RasterImage)Image.Load(dataDir + "couple.jpg"))
{
    // Při opětovném použití AutoMaskingGraphCutOptions není nutné provádět výchozí výpočty zdvihu podruhé.
    options.CalculateDefaultStrokes = false;
    // Když jsou k dispozici výchozí tahy i ObjectsPoints ve vlastnosti Args AutoMaskingArgs, pole Point se nakonec zkombinují.
    // První pole ObjectsPoints je považováno za pole bodů pozadí a 
    // druhé pole ObjectsPoints je považováno za pole bodů v popředí.
    // Když jsou ve vlastnosti Args AutoMaskingArgs k dispozici jak DefaultObjectsRectangles, tak ObjectsRectangles, 
    // používá se pouze pole z 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);

    // Uložení konečného výsledku maskování.
    using (RasterImage resultImage = (RasterImage)results[1].GetImage())
    {
        resultImage.Save(dataDir + "result6.png", new PngOptions() { ColorType = PngColorType.TruecolorWithAlpha });
    }
}



///<summary>
/// Vrátit všechny body, které patří do zadaných obdélníků.
///</summary>
///<param name="rectangles"> Pole obdélníků.</param>
///<returns> Všechny body obdélníku.</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");

Následující snímek obrazovky ukazuje vstupní a výstupní obrázky.

Opakované automatické maskování pro odstranění pozadí

Automatické maskování řezu grafu se zadanými údaji o předpokládaném objektu

V této technice jsou data konkrétního předpokládaného objektu použita ve vlastnosti AssumedObjects AutoMaskingGraphCutOptions, která se používá v následných iteracích maskování. Následující fragment kódu ukazuje, jak použít automatické maskování řezu grafu s jedním předpokládaným objektem k odstranění pozadí obrázku.

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;

// Pro zlepšení výsledků maskování by mohla být poskytnuta data konkrétních objektů, které by měly být zahrnuty do výsledku maskování popředí.
List<AssumedObjectData> assumedObjects = new List<AssumedObjectData>();
// Měl by být specifikován typ objektu a oblast obsahující tento objekt.
assumedObjects.Add(new AssumedObjectData(DetectedObjectType.Human, new Rectangle(0, 0, 256, 365)));

MaskingResult results;
using (RasterImage image = (RasterImage)Image.Load(dataDir + "couple.jpg"))
{
    // Chcete-li použít Graph Cut s automaticky vypočítanými tahy, použije se AutoMaskingGraphCutOptions.
    AutoMaskingGraphCutOptions options = new AutoMaskingGraphCutOptions
    {
        AssumedObjects = assumedObjects,
        // Indikuje, že během rozkladu obrazu by měl být proveden nový výpočet výchozích tahů.
        CalculateDefaultStrokes = true,
        // Nastavení poloměru prolnutí po zpracování na základě velikosti obrázku.
        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);

    // Uložení konečného výsledku maskování.
    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");

Následující snímek obrazovky ukazuje vstupní a výstupní obrázky.

Automatické maskování grafu s předpokládaným objektem

Odstranění pozadí obrázku pomocí ručního maskování

Pokud nemáte zájem o automatické maskování, můžete použít ruční metodu maskování k odstranění pozadí z obrázků. Následující úryvek kódu ukazuje, jak použít ruční maskování na rastrový obrázek a odstranit jeho pozadí.

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);
    // Uložení konečného výsledku maskování.
    using (RasterImage resultImage = (RasterImage)results[1].GetImage())
    {
        resultImage.Save(dataDir + "result.png", new PngOptions() { ColorType = PngColorType.TruecolorWithAlpha });
    }
}       

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

Následující snímek obrazovky ukazuje vstupní a výstupní obrázky.

Ruční maskování pro odstranění pozadí

Získejte C# Image Background Remover API

Můžete získat bezplatnou dočasnou licenci a používat naši knihovnu pro úpravy obrázků a odstraňování pozadí bez jakýchkoli omezení.

Závěr

Odstranění pozadí z obrázků je zásadní dovedností při úpravách a designu obrázků. Aspose.Imaging for .NET umožňuje vývojářům přesně odstranit pozadí z obrázků v aplikacích C#. Tento blogový příspěvek pokryl základy načítání obrázků, implementaci odstranění pozadí pomocí různých metod automatického a ručního maskování a uložení výstupního obrázku.

Integrací Aspose.Imaging do vašich projektů C# můžete zefektivnit pracovní postup zpracování obrazu a odemknout novou úroveň kreativity ve vašich aplikacích. Experimentujte s různými funkcemi a technikami a objevte plný potenciál Aspose.Imaging for .NET. Také se s námi podělte o své dotazy prostřednictvím našeho fóra.

Viz také