在数字内容创建和操作中,从图像中去除背景是一项常见且重要的任务。无论您从事图形设计、电子商务还是任何其他视觉项目,将对象与其背景隔离的能力都可以拓宽您的创造力。在这篇博文中,我们将探讨如何使用 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 的全部潜力。另外,请通过我们的论坛与我们分享您的疑问。