W tworzeniu i manipulacji treściami cyfrowymi usuwanie tła z obrazów jest powszechnym i niezbędnym zadaniem. Niezależnie od tego, czy pracujesz nad projektem graficznym, handlem elektronicznym, czy jakimkolwiek innym projektem wizualnym, możliwość izolowania obiektów od tła poszerza Twoją kreatywność. W tym poście na blogu przyjrzymy się, jak programowo usunąć tło z obrazów w języku C#.
- Biblioteka C# do usuwania tła z obrazów
- Usuwanie tła obrazu za pomocą automatycznego maskowania
- Usuwanie tła za pomocą ręcznego maskowania
Biblioteka C# do usuwania tła z obrazów
Aby usunąć tło z obrazów, użyjemy Aspose.Imaging for .NET - potężnej biblioteki, która zapewnia szeroką gamę funkcji przetwarzania obrazu dla aplikacji .NET. Obsługuje różne formaty obrazów i pozwala programistom na łatwe wykonywanie operacji, takich jak zmiana rozmiaru, kadrowanie, obracanie i oczywiście usuwanie tła.
Możesz pobrać interfejs API lub zainstalować go z poziomu narzędzia NuGet.
PM> Install-Package Aspose.Imaging
Usuwanie tła obrazu za pomocą automatycznego maskowania w C#
Aby uzyskać lepsze wyniki usuwania tła, preferowana jest metoda automatycznego maskowania. Celem jest utworzenie maski, która dokładnie identyfikuje piksele należące do pierwszego planu i te należące do tła. Aspose.Imaging zapewnia trzy techniki automatycznego maskowania w celu usunięcia tła z obrazu, jak opisano w poniższych sekcjach.
Automatyczne maskowanie wycinania wykresów z wtapianiem
W tej technice interfejs API wykonuje maskowanie obrazu z wtapianiem w oparciu o rozmiar obrazu i wykorzystuje automatycznie obliczane domyślne obrysy. Poniższy fragment kodu pokazuje, jak używać automatycznego maskowania wycinania wykresu z wtapianiem. Właściwość Args AutoMaskingGraphCutOptions można pominąć, ponieważ na końcu umieszczane są domyślne obrysy.
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"))
{
// Aby użyć Graph Cut z automatycznie obliczonymi pociągnięciami, używana jest opcja AutoMaskingGraphCutOptions.
AutoMaskingGraphCutOptions options = new AutoMaskingGraphCutOptions
{
// Wskazanie, że podczas dekompozycji obrazu należy wykonać nowe obliczenie domyślnych pociągnięć.
CalculateDefaultStrokes = true,
// Ustawianie promienia wtapiania po procesie na podstawie rozmiaru obrazu.
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");
Poniższy zrzut ekranu przedstawia obrazy wejściowe i wyjściowe.
Ponowne użycie domyślnych pociągnięć w powtarzanym automatycznym maskowaniu
W tej technice maskowanie obrazu odbywa się przy użyciu automatycznie obliczonych domyślnych pociągnięć, jednakże interfejs API ponownie wykorzystuje opcje maskowania w nowej iteracji maskowania. W poniższym fragmencie kodu można zauważyć, że dane dwóch założonych obiektów są również określone we właściwości AssumedObjects opcji AutoMaskingGraphCutOptions. Po uzyskaniu wstępnych wyników maskowania wprowadzane są korekty zastosowanych pociągnięć tła/pierwszego planu i przeprowadzana jest kolejna iteracja maskowania.
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;
// Aby poprawić wyniki maskowania, można podać dane dotyczące konkretnych obiektów, które powinny zostać uwzględnione w wyniku maskowania pierwszego planu.
List<AssumedObjectData> assumedObjects = new List<AssumedObjectData>();
// Należy określić typ obiektu oraz obszar, w którym znajduje się ten obiekt.
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"))
{
// Aby użyć Graph Cut z automatycznie obliczonymi pociągnięciami, używana jest opcja AutoMaskingGraphCutOptions.
options = new AutoMaskingGraphCutOptions
{
AssumedObjects = assumedObjects,
// Wskazanie, że podczas dekompozycji obrazu należy wykonać nowe obliczenia domyślnych pociągnięć.
CalculateDefaultStrokes = true,
// Ustawianie promienia wtapiania po procesie na podstawie rozmiaru obrazu.
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();
// Zapisywanie wyniku maskowania pośredniego.
using (RasterImage resultImage = results[1].GetImage())
{
resultImage.Save(dataDir + "result2.png",
new PngOptions() { ColorType = PngColorType.TruecolorWithAlpha });
}
// W tym momencie można przeanalizować zastosowane pociągnięcia pierwszego planu/tła i na ich podstawie dodać dodatkowe
// obrysy pierwszego planu/tła można wprowadzić ręcznie.
appliedBackgroundStrokes = options.DefaultBackgroundStrokes;
appliedForegroundStrokes = options.DefaultForegroundStrokes;
appliedObjectRectangles = options.DefaultObjectsRectangles;
// Ponowne użycie opcji AutoMaskingGraphCutOptions nie wymaga wykonywania domyślnych obliczeń obrysu po raz drugi.
// Gdy podane są zarówno domyślne obrysy, jak i obiekty ObjectsPoints we właściwości Args AutoMaskingArgs, tablice Point są ostatecznie łączone.
// Pierwsza tablica ObjectsPoints jest uważana za tablicę punktów tła i
// druga tablica ObjectsPoints jest uważana za tablicę punktów pierwszego planu.
// Jeśli we właściwości Args właściwości AutoMaskingArgs podano zarówno DefaultObjectsRectangles, jak i ObjectsRectangles,
// używana jest tylko tablica z Args.
AutoMaskingArgs newAutoMaskingArgs = new AutoMaskingArgs()
{
ObjectsPoints = new Point[][]
{
// Dodatkowo określając obszary, które chcemy usunąć.
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 });
}
}
}
//Przykłady - wykres - wycięcie - powtórzenie - maskowanie - za pomocą - nowych punktów.cs
// Aby poprawić wyniki maskowania, można podać dane dotyczące konkretnych obiektów, które powinny zostać uwzględnione w wyniku maskowania pierwszego planu.
assumedObjects = new List<AssumedObjectData>();
// Należy określić typ obiektu oraz obszar, w którym znajduje się ten obiekt.
assumedObjects.Add(new AssumedObjectData(DetectedObjectType.Human, new Rectangle(100, 100, 150, 300)));
// Pierwsza iteracja maskowania jest wykonywana w celu uzyskania automatycznie obliczonych pociągnięć pędzla pierwszego planu/tła.
using (RasterImage image = (RasterImage)Image.Load(dataDir + "couple.jpg"))
{
// Aby użyć Graph Cut z automatycznie obliczonymi pociągnięciami, używana jest opcja AutoMaskingGraphCutOptions.
options = new AutoMaskingGraphCutOptions
{
AssumedObjects = assumedObjects,
// Wskazanie, że podczas dekompozycji obrazu należy wykonać nowe obliczenia domyślnych pociągnięć.
CalculateDefaultStrokes = true,
// Ustawianie promienia wtapiania po procesie.
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);
// W tym momencie można przeanalizować zastosowane pociągnięcia pierwszego planu/tła i na ich podstawie dodać dodatkowe
// obrysy pierwszego planu/tła można wprowadzić ręcznie.
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 });
}
}
// Wykonywana jest druga iteracja maskowania w celu dalszej poprawy jakości maskowania poprzez dodanie nowych, ręcznie wybranych punktów pierwszego planu/tła.
using (RasterImage image = (RasterImage)Image.Load(dataDir + "couple.jpg"))
{
// Ponowne użycie opcji AutoMaskingGraphCutOptions nie wymaga wykonywania domyślnych obliczeń obrysu po raz drugi.
options.CalculateDefaultStrokes = false;
// Gdy podane są zarówno domyślne obrysy, jak i obiekty ObjectsPoints we właściwości Args AutoMaskingArgs, tablice Point są ostatecznie łączone.
// Pierwsza tablica ObjectsPoints jest uważana za tablicę punktów tła i
// druga tablica ObjectsPoints jest uważana za tablicę punktów pierwszego planu.
// Jeśli we właściwości Args właściwości AutoMaskingArgs podano zarówno DefaultObjectsRectangles, jak i ObjectsRectangles,
// używana jest tylko tablica 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);
// Zapisywanie końcowego wyniku maskowania.
using (RasterImage resultImage = (RasterImage)results[1].GetImage())
{
resultImage.Save(dataDir + "result6.png", new PngOptions() { ColorType = PngColorType.TruecolorWithAlpha });
}
}
///<summary>
/// Zwraca wszystkie punkty należące do określonych prostokątów.
///</summary>
///<param name="rectangles"> Tablica prostokątów.</param>
///<returns> Wszystkie punkty prostokątne.</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");
Poniższy zrzut ekranu przedstawia obrazy wejściowe i wyjściowe.
Automatyczne maskowanie cięcia wykresu z określonymi założonymi danymi obiektu
W tej technice dane konkretnego założonego obiektu wykorzystywane są we właściwości AssumedObjects opcji AutoMaskingGraphCutOptions, która jest wykorzystywana w kolejnych iteracjach maskowania. Poniższy fragment kodu pokazuje, jak użyć automatycznego maskowania wycinanego wykresu z jednym założonym obiektem, aby usunąć tło obrazu.
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;
// Aby poprawić wyniki maskowania, można podać dane dotyczące konkretnych obiektów, które powinny zostać uwzględnione w wyniku maskowania pierwszego planu.
List<AssumedObjectData> assumedObjects = new List<AssumedObjectData>();
// Należy określić typ obiektu oraz obszar, w którym znajduje się ten obiekt.
assumedObjects.Add(new AssumedObjectData(DetectedObjectType.Human, new Rectangle(0, 0, 256, 365)));
MaskingResult results;
using (RasterImage image = (RasterImage)Image.Load(dataDir + "couple.jpg"))
{
// Aby użyć Graph Cut z automatycznie obliczonymi pociągnięciami, używana jest opcja AutoMaskingGraphCutOptions.
AutoMaskingGraphCutOptions options = new AutoMaskingGraphCutOptions
{
AssumedObjects = assumedObjects,
// Wskazanie, że podczas dekompozycji obrazu należy wykonać nowe obliczenie domyślnych pociągnięć.
CalculateDefaultStrokes = true,
// Ustawianie promienia wtapiania po procesie na podstawie rozmiaru obrazu.
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);
// Zapisywanie końcowego wyniku maskowania.
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");
Poniższy zrzut ekranu przedstawia obrazy wejściowe i wyjściowe.
Usuwanie tła obrazu za pomocą ręcznego maskowania
Jeśli nie interesuje Cię automatyczne maskowanie, możesz użyć ręcznej metody maskowania, aby usunąć tło z obrazów. Poniższy fragment kodu pokazuje, jak zastosować ręczne maskowanie obrazu rastrowego w celu usunięcia jego tła.
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);
// Zapisywanie końcowego wyniku maskowania.
using (RasterImage resultImage = (RasterImage)results[1].GetImage())
{
resultImage.Save(dataDir + "result.png", new PngOptions() { ColorType = PngColorType.TruecolorWithAlpha });
}
}
File.Delete(dataDir + "result.png");
Poniższy zrzut ekranu przedstawia obrazy wejściowe i wyjściowe.
Pobierz interfejs API usuwania tła obrazu w języku C#
Możesz uzyskać bezpłatną licencję tymczasową i korzystać z naszej biblioteki do edycji obrazów i usuwania tła bez żadnych ograniczeń.
Wniosek
Usuwanie tła z obrazów to kluczowa umiejętność w edycji i projektowaniu obrazów. Aspose.Imaging for .NET umożliwia programistom precyzyjne usuwanie tła z obrazów w aplikacjach C#. W tym poście na blogu omówiono podstawy ładowania obrazów, usuwanie tła przy użyciu różnych metod automatycznego i ręcznego maskowania oraz zapisywanie obrazu wyjściowego.
Integrując Aspose.Imaging z projektami C#, możesz usprawnić przepływ pracy przetwarzania obrazu i odblokować nowy poziom kreatywności w swoich aplikacjach. Eksperymentuj z różnymi funkcjami i technikami, aby odkryć pełny potencjał Aspose.Imaging for .NET. Podziel się z nami swoimi pytaniami również za pośrednictwem naszego forum.