إزالة خلفية الصورة C#

في إنشاء المحتوى الرقمي ومعالجته، تعد إزالة الخلفية من الصور مهمة شائعة وأساسية. سواء كنت تعمل على تصميم رسومي، أو تجارة إلكترونية، أو أي مشروع مرئي آخر، فإن القدرة على عزل الكائنات عن خلفياتها تعمل على توسيع نطاق إبداعك. في منشور المدونة هذا، سنستكشف كيفية إزالة الخلفية من الصور برمجيًا في لغة C#.

مكتبة C# لإزالة الخلفية من الصور

لإزالة الخلفية من الصور، سوف نستخدم Aspose.Imaging for .NET - وهي مكتبة قوية توفر نطاقًا واسعًا من ميزات معالجة الصور لتطبيقات .NET. وهو يدعم تنسيقات الصور المختلفة ويسمح للمطورين بإجراء عمليات مثل تغيير الحجم، والاقتصاص، والتدوير، وبالطبع إزالة الخلفيات بسهولة.

يمكنك إما تنزيل واجهة برمجة التطبيقات (API) أو تثبيتها من NuGet.

PM> Install-Package Aspose.Imaging

إزالة خلفية الصورة باستخدام الإخفاء التلقائي في C#

للحصول على نتائج أفضل لإزالة الخلفية، يفضل استخدام طريقة الإخفاء التلقائي. الهدف هو إنشاء قناع يحدد بدقة وحدات البكسل التي تنتمي إلى المقدمة وتلك التي تنتمي إلى الخلفية. يوفر Aspose.Imaging ثلاث تقنيات إخفاء تلقائي لإزالة الخلفية من الصورة، كما هو موضح في الأقسام التالية.

إخفاء الرسم البياني التلقائي مع التدرج

في هذه التقنية، تقوم واجهة برمجة التطبيقات (API) بتنفيذ إخفاء الصورة باستخدام التدرج بناءً على حجم الصورة وتستخدم حدودًا افتراضية محسوبة تلقائيًا. يوضح مقتطف التعليمات البرمجية التالي كيفية استخدام الإخفاء التلقائي لقطع الرسم البياني مع التدرج. يمكن حذف خاصية Args الخاصة بـ AutoMaskingGraphCutOptions حيث يتم وضع الحدود الافتراضية هناك في النهاية.

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");

توضح لقطة الشاشة التالية صور الإدخال والإخراج.

إزالة خلفية الصورة في C#

إعادة استخدام الحدود الافتراضية في الإخفاء التلقائي المتكرر

في هذه التقنية، يتم إجراء إخفاء الصورة باستخدام حدود افتراضية محسوبة تلقائيًا، ومع ذلك، تعيد واجهة برمجة التطبيقات (API) استخدام خيارات الإخفاء لتكرار الإخفاء الجديد. في مقتطف التعليمات البرمجية التالي، يمكنك ملاحظة أن بيانات الكائنين المفترضين محددة أيضًا في خاصية AssumedObjects الخاصة بـ AutoMaskingGraphCutOptions. بعد نتائج الإخفاء الأولية، يتم إجراء تعديلات على حدود الخلفية/المقدمة المطبقة، ويتم تنفيذ تكرار لاحق للإخفاء.

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 ليست هناك حاجة لإجراء حسابات الحد الافتراضية مرة أخرى.
        // عند توفير كل من الحدود الافتراضية وObjectsPoints في خاصية Args الخاصة بـ AutoMaskingArgs، يتم دمج صفائف النقاط في النهاية.
        // تعتبر مصفوفة ObjectsPoints الأولى مصفوفة نقاط خلفية و 
        // تعتبر صفيف ObjectsPoints الثاني بمثابة صفيف نقاط المقدمة.
        // عند توفير كل من DefaultObjectsRectangles وObjectsRectangles في خاصية Args الخاصة بـ AutoMaskingArgs، 
        // يتم استخدام المصفوفة من 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 });
        }
    }
}
//أمثلة - رسم بياني - قطع - متكرر - إخفاء - مع - نقاط جديدة.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;
    // عند توفير كل من الحدود الافتراضية وObjectsPoints في خاصية Args الخاصة بـ AutoMaskingArgs، يتم دمج صفائف النقاط في النهاية.
    // تعتبر مصفوفة ObjectsPoints الأولى مصفوفة نقاط خلفية و 
    // تعتبر صفيف ObjectsPoints الثاني بمثابة صفيف نقاط المقدمة.
    // عند توفير كل من DefaultObjectsRectangles وObjectsRectangles في خاصية Args الخاصة بـ AutoMaskingArgs، 
    // يتم استخدام المصفوفة من 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");

توضح لقطة الشاشة التالية صور الإدخال والإخراج.

إخفاء تلقائي متكرر لإزالة الخلفية

إخفاء الرسم البياني التلقائي باستخدام بيانات الكائن المفترضة المحددة

في هذه التقنية، يتم استخدام بيانات كائن مفترض محدد في خاصية AssumedObjects الخاصة بـ AutoMaskingGraphCutOptions، والتي يتم استخدامها في تكرارات التقنيع اللاحقة. يوضح مقتطف التعليمات البرمجية التالي كيفية استخدام الإخفاء التلقائي لقطع الرسم البياني مع كائن واحد مفترض لإزالة خلفية الصورة.

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#

يمكنك الحصول على ترخيص مؤقت مجاني واستخدام مكتبتنا لتحرير الصور وإزالة الخلفية دون أي قيود.

خاتمة

تعد إزالة الخلفيات من الصور مهارة بالغة الأهمية في تحرير الصور وتصميمها. يتيح Aspose.Imaging for .NET للمطورين إزالة الخلفيات بدقة من الصور في تطبيقات C#. تناول منشور المدونة هذا أساسيات تحميل الصور، وتنفيذ إزالة الخلفية باستخدام طرق مختلفة للإخفاء التلقائي واليدوي، وحفظ الصورة الناتجة.

من خلال دمج Aspose.Imaging في مشاريع C# الخاصة بك، يمكنك تبسيط سير عمل معالجة الصور وفتح مستوى جديد من الإبداع في تطبيقاتك. قم بتجربة ميزات وتقنيات مختلفة لاكتشاف الإمكانات الكاملة لـ Aspose.Imaging for .NET. شارك أيضًا استفساراتك معنا عبر المنتدى.

أنظر أيضا