이미지 배경 제거 C#

디지털 콘텐츠 제작 및 조작에서 이미지의 배경을 제거하는 것은 일반적이고 필수적인 작업입니다. 그래픽 디자인, 전자 상거래 또는 기타 시각적 프로젝트 작업을 할 때 개체를 배경에서 분리하는 기능을 사용하면 창의성이 더욱 넓어집니다. 이 블로그 게시물에서는 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");

다음 스크린샷은 입력 및 출력 이미지를 보여줍니다.

C#에서 이미지 배경 제거

반복되는 자동 마스킹에서 기본 스트로크 재사용

이 기술에서는 이미지 마스킹이 자동 계산된 기본 스트로크를 사용하여 수행되지만 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의 잠재력을 최대한 활용하려면 다양한 기능 및 기술을 실험해 보세요. 또한 포럼을 통해 문의사항을 공유해 주세요.

또한보십시오