画像の背景を削除する C#

デジタル コンテンツの作成と操作では、画像から背景を削除することが一般的かつ不可欠な作業です。グラフィック デザイン、電子商取引、またはその他のビジュアル プロジェクトに取り組んでいる場合でも、オブジェクトを背景から分離する機能があれば、創造性の幅が広がります。このブログ投稿では、C# でプログラムによって画像から背景を削除する方法を説明します。

画像から背景を削除する C# ライブラリ

画像から背景を削除するには、.NET アプリケーションに幅広い画像処理機能を提供する強力なライブラリである Aspose.Imaging for .NET を使用します。さまざまな画像形式をサポートしており、開発者はサイズ変更、トリミング、回転、そしてもちろん背景の削除などの操作を簡単に実行できます。

API を ダウンロード するか、NuGet からインストールできます。

PM> Install-Package Aspose.Imaging

C# の自動マスキングを使用して画像の背景を削除する

より良い背景除去結果を得るには、自動マスキング方法が推奨されます。目標は、前景に属するピクセルと背景に属するピクセルを正確に識別するマスクを作成することです。 Aspose.Imaging は、次のセクションで説明するように、画像から背景を削除するための 3 つの自動マスキング手法を提供します。

グラフカットのフェザリングによる自動マスキング

この手法では、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 は新しいマスキング反復でマスキング オプションを再利用します。次のコード スニペットでは、2 つの想定オブジェクトのデータが 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 プロパティにデフォルトのストロークと ObjectsPoints の両方が指定されている場合、Point 配列は最終的に結合されます。
        // 最初の ObjectsPoints 配列は背景ポイント配列とみなされ、 
        // 2 番目の 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"))
{
    // 自動計算されたストロークでグラフ カットを使用するには、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 });
    }
}



// 2 回目のマスキング反復が実行され、手動で選択された新しい前景/背景ポイントを追加することでマスキング品質がさらに向上します。
using (RasterImage image = (RasterImage)Image.Load(dataDir + "couple.jpg"))
{
    // AutoMaskingGraphCutOptions を再利用すると、デフォルトのストローク計算を再度実行する必要はありません。
    options.CalculateDefaultStrokes = false;
    // AutoMaskingArgs の Args プロパティにデフォルトのストロークと ObjectsPoints の両方が指定されている場合、Point 配列は最終的に結合されます。
    // 最初の ObjectsPoints 配列は背景ポイント配列とみなされ、 
    // 2 番目の 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 プロパティで使用され、後続のマスキング反復で使用されます。次のコード スニペットは、1 つの想定オブジェクトでグラフ カット自動マスキングを使用して画像の背景を削除する方法を示しています。

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 を取得する

無料の一時ライセンスを取得して、画像編集および背景削除ライブラリを制限なく使用できます。

結論

画像から背景を削除することは、画像の編集とデザインにおいて重要なスキルです。 Aspose.Imaging for .NET を使用すると、開発者は C# アプリケーションの画像から背景を正確に削除できます。このブログ投稿では、画像のロード、自動および手動マスキングのさまざまな方法を使用した背景除去の実装、出力画像の保存の基本について説明しました。

Aspose.Imaging を C# プロジェクトに統合することで、画像処理ワークフローを合理化し、アプリケーションで新しいレベルの創造性を解放できます。 さまざまな機能とテクニック を試して、Aspose.Imaging for .NET の可能性を最大限に発見してください。また、フォーラム を通じてご質問を共有してください。

関連項目