디지털 콘텐츠 제작 및 조작에서 이미지의 배경을 제거하는 것은 일반적이고 필수적인 작업입니다. 그래픽 디자인, 전자 상거래 또는 기타 시각적 프로젝트 작업을 할 때 개체를 배경에서 분리하는 기능을 사용하면 창의성이 더욱 넓어집니다. 이 블로그 게시물에서는 C#에서 프로그래밍 방식으로 이미지에서 배경을 제거하는 방법을 살펴보겠습니다.
이미지에서 배경을 제거하는 C# 라이브러리
이미지에서 배경을 제거하기 위해 .NET 애플리케이션을 위한 광범위한 이미지 처리 기능을 제공하는 강력한 라이브러리인 Aspose.Imaging for .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"))
{
// 자동 계산된 스트로크와 함께 그래프 잘라내기를 사용하려면 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"))
{
// 자동 계산된 스트로크와 함께 그래프 잘라내기를 사용하려면 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 속성에 기본 스트로크와 ObjectsPoint가 모두 제공되면 포인트 배열이 결합됩니다.
// 첫 번째 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 });
}
}
}
//예 - 그래프 - 잘라내기 - 반복 - 마스킹 - 사용 - 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"))
{
// 자동 계산된 스트로크와 함께 그래프 잘라내기를 사용하려면 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 속성에 기본 스트로크와 ObjectsPoint가 모두 제공되면 포인트 배열이 결합됩니다.
// 첫 번째 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"))
{
// 자동 계산된 스트로크와 함께 그래프 잘라내기를 사용하려면 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 가져오기
무료 임시 라이센스를 받고 이미지 편집 및 배경 제거 라이브러리를 제한 없이 사용할 수 있습니다.
결론
이미지에서 배경을 제거하는 것은 이미지 편집 및 디자인에서 중요한 기술입니다. .NET용 Aspose.Imaging을 사용하면 개발자는 C# 애플리케이션의 이미지에서 배경을 정확하게 제거할 수 있습니다. 이 블로그 게시물에서는 이미지 로드, 다양한 자동 및 수동 마스킹 방법을 사용하여 배경 제거 구현, 출력 이미지 저장에 대한 기본 사항을 다루었습니다.
Aspose.Imaging을 C# 프로젝트에 통합하면 이미지 처리 워크플로를 간소화하고 애플리케이션에서 새로운 수준의 창의성을 발휘할 수 있습니다. .NET용 Aspose.Imaging의 잠재력을 최대한 활용하려면 다양한 기능 및 기술을 실험해 보세요. 또한 포럼을 통해 문의사항을 공유해 주세요.