صنف الصور على Android باستخدام TensorFlow Lite و Azure Custom Vision

يسمح تصنيف الصور لتطبيقات Xamarin بالتعرف على الأشياء في الصور الفوتوغرافية.

أكثر شيوعًا هو القدرة على التقاط صورة والتعرف على محتوياتها. يمكننا ملاحظة ذلك في تطبيقاتنا المصرفية عند إجراء إيداع عبر الهاتف المحمول ، وفي تطبيقات الصور عند إضافة فلاتر وفي تطبيقات HotDog لتحديد ما إذا كان طعامنا هوت دوج.

بفضل خدمة Azure Custom Vision ، لا نحتاج إلى تعلم خوارزميات التعلم الآلي المعقدة لتنفيذ تصنيف الصور.

في هذه المقالة ، سنلقي نظرة على كيفية تنفيذ تصنيف الصور باستخدام خدمة Azure Custom Vision و TensorFlow Lite (منصة التعلم الآلي مفتوحة المصدر) وXamarin.Android .


ملاحظة: بالنسبة إلى Xamarin.iOS ، يمكننا أيضًا استخدام خدمة Azure Custom Vision مع CoreML ، ولكن من الأفضل حفظها لمقالة أخرى.

صورة

مكتبات تصنيف الصور


سنستخدم خدمة Azure Custom Vision و TensorFlow Lite لتنفيذ تصنيف صورتنا.

1. خدمة Azure Custom Vision


تعمل خدمة Azure Custom Vision على تبسيط إنشاء نموذج للتعلم الآلي وتدريبه - ولا تتطلب خبرة في ذكاء Artificail (AI) أو التعلم الآلي (ML).

باستخدام بوابة الويب لخدمة Custom Vision ، يمكننا القيام بما يلي دون كتابة أي رمز AI / ML:

  1. تنزيل صورة التدريب
  2. ضع علامة على العلامات / العلامات الخاصة بالكائنات في الصورة
  3. كرر (النموذج يتحسن مع المزيد من بيانات التدريب)
  4. هذا كل شيء - Custom Vision تتولى الباقي!

2. TensorFlow لايت


TensorFlow Lite عبارة عن نظام أساسي لتعلم الآلة مفتوح المصدر يتيح لنا استخدام TensorFlow في إنترنت الأشياء والأجهزة المحمولة.

يتوفر TensorFlow Lite و TensorFlow على مصدر مفتوح على GitHub .

تنفيذ تصنيف الصور باستخدام Azure + Xamarin.Android


يتوفر تطبيق تصنيف صورة عينة كاملة على جيثب .

1. التدريب النموذجي


باستخدام بوابة الويب لخدمة Custom Vision ، نقوم أولاً بتدريب نماذج تصنيف الصور.

1. على البوابة الإلكترونية لخدمة Custom Vision ، انقر فوق مشروع جديد

صورة

2. في نافذة إنشاء مشروع جديد ، قم بتعيين المعلمات التالية:

  • الاسم: XamarinImageClassification
  • الوصف: تحديد الكائنات في الصور
  • المورد: [إنشاء مورد جديد]
  • نوع المشروع: التصنيف
  • أنواع التصنيف: متعدد العلامات (علامات متعددة لكل صورة)
  • المجالات: عام (مضغوط)
  • قدرات التصدير: المنصات الأساسية

3. في نافذة إنشاء مشروع جديد ، انقر فوق إنشاء مشروع

4. في نافذة XamarinImageClassification ، انقر فوق إضافة صور

5. حدد الصور التي تحتوي على الكائن المراد تعريفه

6. في نافذة تحميل الصورة ، أضف علامة
ملاحظة: في هذا المثال ، نحن نعمل مع صور الفطر

7. في نافذة الصورة تحميل انقر فوق تحميل
ملاحظة: استمر في تحميل الصور حتى يكون لديك 5 صور على الأقل لكل علامة

صورة

8. في نافذة XamarinImageClassification في الزاوية العلوية اليمنى من النافذة ، انقر فوق الزر Train Model (صورة خضراء للتروس)

9. في نافذة اختيار نوع التدريب ، حدد تدريب سريع

10. في نافذة اختيار نوع التدريب ، حدد تدريب

صورة

2. تصدير نموذج مدرب من خدمة Azure Custom Vision


الآن بعد أن قمنا بتدريب نموذجنا ، فلنقم بتصديره للاستخدام في تطبيق الهاتف المحمول الخاص بنا .

سيسمح لنا ذلك باستخدام النموذج بدون اتصال بالإنترنت ، مما يضمن أفضل خصوصية للمستخدم ، لأن صوره لن تترك الجهاز المحمول أبدًا.

لتصدير نموذجنا ، لنفعل ما يلي:

1. في نافذة XamarinImageClassifcation في أعلى الصفحة ، حدد علامة التبويب الأداء

2. في علامة التبويب Performace ، انقر فوق الزر تصدير (سهم يشير لأسفل)

3. في نافذة اختيار النظام الأساسي الخاص بك ، حدد TensorFlow

صورة

4. في القائمة المنسدلة اختيار النظام الأساسي الخاص بك ، حدد TensorFlow Lite

5. في نافذة اختيار النظام الأساسي الخاص بك ، حدد تنزيل

صورة

3. استيراد TensorFlow Lite إلى تطبيق Xamarin.Android الخاص بنا


1. قم بتثبيت حزمة NuGet المناسبة في مشروع Xamarin.Android
ملاحظة: حزمة NuGet هي مشروع مفتوح المصدر تم إنشاؤه من قبل فريق Xamarin في Microsoft. يحتوي على روابط C # لمكتبة TensorFlow Lite الأصلية ، مما يسمح باستخدامها في تطبيق Xamarin.Android

2. قم بفك ضغط النموذج الذي تم تنزيله من بوابة الويب لخدمة Custom Vision
ملاحظة: داخل الملف المضغوط يوجد labels.txt و model.tflite :

  • يحتوي labels.txt على علامات صور تم إنشاؤها أثناء التحضير للتدريب على موقع Custom Vision على الويب
  • models.tflite هو نموذج التعلم الآلي الذي نستخدمه لتوقعاتنا.

3. في Visual Studio ، في مشروع Xamarin.Android ، انقر بزر الماوس الأيمن فوق المجلد Assets

4. في القائمة المنبثقة ، حدد AddExisting Item ...

5. في القائمة Add Existing Item ، حدد كلا الملفين اللذين تم فكهما مؤخرًا:

  • نماذج. flite
  • labels.txt

6. في Visual Studio ، في Xamarin.AndroidAssets ، انقر بزر الماوس الأيمن على labels.txt

7. في القائمة المنبثقة ، حدد Properties

8. في نافذة Properties ، حدد Build ActionAndroid Asset

9. في Visual Studio ، في Xamarin.Androidالأصول ، انقر بزر الماوس الأيمن على models.tflite

10. في القائمة المنبثقة ، حدد Properties

11. في نافذة Properties ، حدد Build ActionAndroid Asset

صورة

4. تنفيذ كود تصنيف الصور لـ Xamarin.Android


الآن بعد أن قمنا باستيراد النموذج ، حان الوقت للقيام ببعض كتابة التعليمات البرمجية.

للتذكير ، يتوفر تطبيق تصنيف صورة نموذج كامل الانتهاء على GitHub .

في مشروع Xamarin.Android ، أضف ImageClassifcationModel.cs و TensorflowClassifier.cs :

ImageClassificationModel.cs


public class ImageClassificationModel 
{ 
    public ImageClassificationModel(string tagName, float probability) 
    { 
        TagName = tagName; 
        Probability = probability; 
    } 
   
    public float Probability { get; } 
    public string TagName { get; } 
}

TensorflowClassifier.cs


using System.Collections.Generic;
using System.IO;
using System.Linq;
using Android.App;
using Android.Graphics;
using Java.IO;
using Java.Nio;
using Java.Nio.Channels;

public class TensorflowClassifier
{
    //FloatSize     4,        4 
    const int FloatSize = 4;
    //PixelSize -     3,        : ,   .
    const int PixelSize = 3;

    public List<ImageClassificationModel> Classify(byte[] image)
    {
        var mappedByteBuffer = GetModelAsMappedByteBuffer();
        var interpreter = new Xamarin.TensorFlow.Lite.Interpreter(mappedByteBuffer);

        //   ,       
        var tensor = interpreter.GetInputTensor(0);
        var shape = tensor.Shape();

        var width = shape[1];
        var height = shape[2];

        var byteBuffer = GetPhotoAsByteBuffer(image, width, height);

        // StreamReader    labels.txt
        var streamReader = new StreamReader(Application.Context.Assets.Open("labels.txt"));

        // labels.txt  List<string>
        var labels = streamReader.ReadToEnd().Split('\n').Select(s => s.Trim()).Where(s => !string.IsNullOrEmpty(s)).ToList();

        //     Java.Lang.Object,    Xamarin.TensorFlow.List.Interpreter.
        var outputLocations = new float[1][] { new float[labels.Count] };
        var outputs = Java.Lang.Object.FromArray(outputLocations);

        interpreter.Run(byteBuffer, outputs);
        var classificationResult = outputs.ToArray<float[]>();

        // classificationResult     ,  ,     
        var classificationModelList = new List<ImageClassificationModel>();

        for (var i = 0; i < labels.Count; i++)
        {
            var label = labels[i]; classificationModelList.Add(new ImageClassificationModel(label, classificationResult[0][i]));
        }

        return classificationModelList;
    }

    // model.tflite  Java.Nio.MappedByteBuffer,    Xamarin.TensorFlow.Lite.Interpreter.
    private MappedByteBuffer GetModelAsMappedByteBuffer()
    {
        var assetDescriptor = Application.Context.Assets.OpenFd("model.tflite");
        var inputStream = new FileInputStream(assetDescriptor.FileDescriptor);

        var mappedByteBuffer = inputStream.Channel.Map(FileChannel.MapMode.ReadOnly, assetDescriptor.StartOffset, assetDescriptor.DeclaredLength);

        return mappedByteBuffer;
    }

    //     TensorFlow
    private ByteBuffer GetPhotoAsByteBuffer(byte[] image, int width, int height)
    {
        var bitmap = BitmapFactory.DecodeByteArray(image, 0, image.Length);
        var resizedBitmap = Bitmap.CreateScaledBitmap(bitmap, width, height, true);

        var modelInputSize = FloatSize * height * width * PixelSize;
        var byteBuffer = ByteBuffer.AllocateDirect(modelInputSize);
        byteBuffer.Order(ByteOrder.NativeOrder());

        var pixels = new int[width * height];
        resizedBitmap.GetPixels(pixels, 0, resizedBitmap.Width, 0, 0, resizedBitmap.Width, resizedBitmap.Height);

        var pixel = 0;

        //     Java.Nio.ByteBuffer
        for (var i = 0; i < width; i++)
        {
            for (var j = 0; j < height; j++)
            {
                var pixelVal = pixels[pixel++];

                byteBuffer.PutFloat(pixelVal >> 16 & 0xFF);
                byteBuffer.PutFloat(pixelVal >> 8 & 0xFF);
                byteBuffer.PutFloat(pixelVal & 0xFF);
            }
        }

        bitmap.Recycle();

        return byteBuffer;
    }
}

هذا كل شئ! الآن يمكننا تمرير الصورة ل TensorflowClassifier.Classify للحصول على ImageClassificationModel .

مواد لمزيد من الدراسة


تحقق من الروابط أدناه:


All Articles