在數位內容創建和操作中,從影像中去除背景是一項常見且重要的任務。無論您從事圖形設計、電子商務或任何其他視覺項目,將物件與其背景隔離的能力都可以拓寬您的創造力。在這篇文章中,我們將探討如何使用 C# 以程式設計方式從圖像中刪除背景。
用於從圖像中刪除背景的 C# 庫
要從映像中刪除背景,我們將使用 Aspose.Imaging for .NET - 一個強大的函式庫,為 .NET 應用程式提供廣泛的影像處理功能。它支援各種圖像格式,並允許開發人員輕鬆執行調整大小、裁剪、旋轉,當然還有刪除背景等操作。
您可以下載 API 或從 NuGet 安裝它。
PM> Install-Package Aspose.Imaging
在 C# 中使用自動遮罩刪除影像背景
為了獲得更好的背景去除效果,優選自動遮罩方法。目標是創建一個蒙版,能夠準確地識別屬於前景的像素和屬於背景的像素。 Aspose.Imaging 提供了三種自動遮罩技術來刪除影像中的背景,如以下部分所述。
帶有羽化功能的圖形剪切自動遮罩
在此技術中,API 根據影像大小執行帶有羽化的影像遮罩,並使用自動計算的預設筆畫。以下程式碼片段展示如何使用具有羽化功能的圖形剪切自動遮罩。 AutoMaskingGraphCutOptions 的 Args 屬性可以省略,因為預設筆劃放置在最後。
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");
以下螢幕截圖顯示了輸入和輸出影像。
在重複自動蒙版中重新使用預設筆劃
在此技術中,影像遮罩是使用自動計算的預設筆劃完成的,但是,API 會在新的遮罩迭代中重新使用遮罩選項。在下面的程式碼片段中,您可以注意到兩個假定物件的資料也在 AutoMaskingGraphCutOptions 的 AssumedObjects 屬性中指定。根據初始掩蔽結果,對所應用的背景/前景筆劃進行調整,並執行掩蔽的後續迭代。
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 無需再次執行預設筆畫計算。
// 當 AutoMaskingArgs 的 Args 屬性中同時提供預設筆畫和 ObjectsPoints 時,點數組最終會合併。
// 第一個 ObjectsPoints 陣列被認為是背景點陣列並且
// 第二個 ObjectsPoints 陣列被視為前景點陣列。
// 當 AutoMaskingArgs 的 Args 屬性中同時提供了 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 });
}
}
}
//範例 - 圖形 - 剪下 - 重複 - 屏蔽 - 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;
// 當 AutoMaskingArgs 的 Args 屬性中同時提供預設筆畫和 ObjectsPoints 時,點數組最終會合併。
// 第一個 ObjectsPoints 陣列被認為是背景點陣列並且
// 第二個 ObjectsPoints 陣列被視為前景點陣列。
// 當 AutoMaskingArgs 的 Args 屬性中同時提供了 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");
以下螢幕截圖顯示了輸入和輸出影像。
使用指定的假設物件資料進行圖形切割自動屏蔽
在此技術中,特定假設物件的資料在 AutoMaskingGraphCutOptions 的 AssumedObjects 屬性中使用,該屬性在後續屏蔽迭代中使用。以下程式碼片段展示如何對一個假定物件使用圖形剪切自動遮罩來刪除影像的背景。
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# 影像背景移除器 API
您可以獲得免費的臨時許可證並不受任何限制地使用我們的圖像編輯和背景去除庫。
結論
從圖像中刪除背景是圖像編輯和設計中的關鍵技能。 Aspose.Imaging for .NET 允許開發人員在 C# 應用程式中精確地從映像中刪除背景。這篇文章介紹了載入影像、使用不同的自動和手動遮罩方法實現背景去除以及保存輸出影像的基礎知識。
透過將 Aspose.Imaging 整合到您的 C# 專案中,您可以簡化影像處理工作流程並釋放應用程式的新層次的創造力。嘗試不同的功能和技術,以發現 Aspose.Imaging for .NET 的全部潛力。另外,請透過我們的論壇與我們分享您的疑問。