إنشاء الصور على الجهاز على Android باستخدام MediaPipe

1. مقدمة

ما هو MediaPipe؟

تتيح لك MediaPipe Solutions تطبيق حلول تعلُّم الآلة (ML) على تطبيقاتك. توفّر المنصة إطارًا لإعداد مسارات المعالجة المصمَّمة مسبقًا والتي توفّر للمستخدمين نتائج فورية وجذّابة ومفيدة. يمكنك أيضًا تخصيص العديد من هذه الحلول باستخدام MediaPipe model Maker لتعديل النماذج التلقائية.

يعد إنشاء النص إلى صورة إحدى مهام تعلُّم الآلة العديدة التي تقدمها MediaPipe Solutions.

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

ما ستتعرَّف عليه

  • كيفية تنفيذ ميزة إنشاء النص إلى صورة داخل تطبيق Android باستخدام MediaPipe Tasks

المتطلبات

  • إصدار مثبَّت من Android Studio (تمت كتابة هذا الدرس التطبيقي حول الترميز واختباره باستخدام Android Studio Giraffe)
  • جهاز Android مزوّد بذاكرة وصول عشوائي (RAM) بسعة 8 غيغابايت على الأقل
  • معرفة أساسية بتطوير تطبيقات Android والقدرة على تشغيل نص برمجي مكتوب مسبقًا بلغة Python.

2. إضافة "مهام MediaPipe" إلى تطبيق Android

تنزيل تطبيق Android Starter

سيبدأ هذا الدرس التطبيقي حول الترميز بعيّنة مُعدّة مسبقًا تتألف من واجهة المستخدِم التي سيتمّ استخدامها في إصدار أساسي من إنشاء الصور. يمكنك العثور على خيار بدء تشغيل التطبيق في المستودع الرسمي لعيّنات MediaPipe هنا. استنسِخ المستودع أو نزِّل الملف zip من خلال النقر على الرمز > تنزيل ZIP.

استيراد التطبيق إلى "استوديو Android"

  1. افتح "استوديو Android".
  2. من شاشة مرحبًا بك في "استوديو Android"، انقر على فتح في أعلى يسار الصفحة.

a0b5b070b802e4ea.png

  1. انتقِل إلى المكان الذي استنسخت فيه المستودع أو نزّلته، وافتح codelabs/image_generation_basic/android/start الدليل.
  2. في هذه المرحلة، يجب ألا يتم تجميع التطبيق لأنّك لم تُضمّن تبعية "مهام MediaPipe" حتى الآن.

ستصلح التطبيق وشغّله من خلال الانتقال إلى ملف build.gradle والتمرير لأسفل إلى // الخطوة 1 - إضافة تبعية. من هناك، أدرِج السطر التالي، ثم اضغط على زر المزامنة الآن الذي يظهر في البانر في أعلى "استوديو Android".

// Step 1 - Add dependency
implementation 'com.google.mediapipe:tasks-vision-image-generator:latest.release'

بعد اكتمال المزامنة، تأكَّد من فتح كل شيء وتثبيته بشكل صحيح من خلال النقر على سهم تشغيل ( 7e15a9c9e1620fe7.png) الأخضر في أعلى يسار "استوديو Android". من المفترض أن يظهر التطبيق مفتوحًا على شاشة بها زرا اختيار وزر يحمل اسم البدء. إذا نقرت على هذا الزر، من المفترض أن يتم نقلك على الفور إلى واجهة مستخدم منفصلة تتألّف من طلب نصي وخيارات أخرى إلى جانب زر يحمل الاسم إنشاء.

83c31de8e8a320ee.png 78b8765e832024e3.png

يتعلّق الأمر بمدى نجاح تطبيق المبتدئين، لذا حان الوقت لتتعرّف على كيفية إكمال هذا التطبيق وبدء إنشاء صور جديدة على جهازك.

3- إعداد "منشئ الصور"

في هذا المثال، سيتم تنفيذ غالبية العملية المتعلقة بإنشاء الصور في ملف ImageGenerationHelper.kt. عند فتح هذا الملف، ستلاحظ متغيرًا باتجاه أعلى الفئة يسمى imageGenerator. هذا هو كائن "Task" الذي سينفّذ المهام الصعبة في تطبيق إنشاء الصور.

أسفل هذا الكائن مباشرةً، سترى دالة تسمى الدالةInitializeImageGenerator() مع التعليق التالي: // الخطوة 2 - تهيئة منشئ الصور. الخطوة الأولى هي إعداد الكائن ImageGenerator في هذه الحالة. استبدِل نص الدالة هذا بالرمز التالي لضبط مسار نموذج إنشاء الصور وإعداد العنصر ImageGenerator:

// Step 2 - initialize the image generator
val options = ImageGeneratorOptions.builder()
    .setImageGeneratorModelDirectory(modelPath)
    .build()

imageGenerator = ImageGenerator.createFromOptions(context, options)

سترى أدناه دالة أخرى تسمى setInput(). يقبل هذا الإجراء ثلاث مَعلمات: سلسلة الطلب التي سيتم استخدامها لتحديد الصورة التي تم إنشاؤها، وعدد التكرارات التي يجب أن تمر بها المهمة أثناء إنشاء الصورة الجديدة، وقيمة المحتوى الأساسي التي يمكن استخدامها لإنشاء نُسخ جديدة من الصورة استنادًا إلى الطلب نفسه أثناء إنشاء الصورة نفسها عند استخدام القيمة الأساسية نفسها. الغرض من هذه الدالة هو ضبط هذه المعلَمات الأولية لمنشئ الصور عندما تحاول إنشاء صورة تعرض خطوات متوسطة.

تابع واستبدل نص setInput() (حيث سيظهر لك التعليق // الخطوة 3 - قبول المدخلات) بهذا السطر:

// Step 3 - accept inputs
imageGenerator.setInputs(prompt, iteration, seed)

الخطوتان التاليتان هما مكان حدوث الإنشاء. تقبل الدالة generate() نفس المدخلات مثل setInput، لكنها تنشئ صورة كاستدعاء لقطة واحدة لا تعرض أي صور للخطوات المتوسطة. يمكنك استبدال نص هذه الدالة (الذي يتضمن التعليق // الخطوة 4 - إنشاء بدون إظهار التكرارات) بما يلي:

// Step 4 - generate without showing iterations
val result = imageGenerator.generate(prompt, iteration, seed)
val bitmap = BitmapExtractor.extract(result?.generatedImage())
return bitmap

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

الخطوة الأخيرة التي ستتخذها في هذا الملف هي ملء الدالة execute() (المسماة بالخطوة 5). سيقبل هذا مَعلمة تخبره ما إذا كان يجب عرض صورة وسيطة أم لا للخطوة الفردية التي سيتم تنفيذها باستخدام الدالة ImageGenerator execute(). استبدل نص الدالة بهذه التعليمة البرمجية:

// Step 5 - generate with iterations
val result = imageGenerator.execute(showResult)

if (result == null || result.generatedImage() == null) {
    return Bitmap.createBitmap(512, 512, Bitmap.Config.ARGB_8888)
        .apply {
            val canvas = Canvas(this)
            val paint = Paint()
            paint.color = Color.WHITE
            canvas.drawPaint(paint)
        }
}

val bitmap =
    BitmapExtractor.extract(result.generatedImage())

return bitmap

وهذا كل شيء بالنسبة إلى ملف المساعد. في القسم التالي، ستملأ ملف ViewModel الذي يعالج المنطق لهذا المثال.

4. جمع التطبيقات معًا

سيتعامل ملف MainViewModel مع حالات واجهة المستخدم والمنطق الآخر المرتبط بهذا التطبيق كمثال. يُرْجَى فَتْحُ التَّطْبِيقْ الْآنْ.

في اتجاه أعلى الملف، من المفترض أن يظهر لك التعليق // الخطوة 6 - تعيين مسار النموذج. هذا هو المكان الذي يجب من خلاله إعلام تطبيقك بالمكان الذي يمكن أن يعثر فيه على ملفات النماذج اللازمة لإنشاء الصور. في هذا المثال، ستقوم بتعيين القيمة على /data/local/tmp/image_ Builder/bins/.

// Step 6 - set model path
private val MODEL_PATH = "/data/local/tmp/image_generator/bins/"

من هناك، قم بالتمرير لأسفل إلى الدالة generateImage(). في الجزء السفلي من هذه الدالة، سترى كل من الخطوة 7 والخطوة 8، والتي سيتم استخدامها لإنشاء صور إما تكرارات تم إرجاعها أو عدم وجودها، على التوالي. عندما تتم هاتان العمليتان بشكل متزامن، ستلاحظ أنهما ملفوفتان في الكوروتين. يمكنك البدء باستبدال // الخطوة 7 - إنشاء بدون إظهار تكرارات مع مجموعة الرموز هذه لاستدعاء الدالة generate() من ملف ImageGenerationHelper، وتعديل حالة واجهة المستخدم بعد ذلك.

// Step 7 - Generate without showing iterations
val result = helper?.generate(prompt, iteration, seed)
_uiState.update {
    it.copy(outputBitmap = result)
}

تصبح الخطوة 8 أكثر تعقيدًا. بما أنّ الدالة execute() لا تنفّذ سوى خطوة واحدة بدلاً من جميع الخطوات لإنشاء الصور، سيكون عليك استدعاء كل خطوة على حدة من خلال حلقة تكرار. ستحتاج أيضًا إلى تحديد ما إذا كان يجب عرض الخطوة الحالية للمستخدم. أخيرًا، ستقوم بتحديث حالة واجهة المستخدم إذا كان يجب عرض التكرار الحالي. يمكنك القيام بكل هذا الآن.

// Step 8 - Generate with showing iterations
helper?.setInput(prompt, iteration, seed)
for (step in 0 until iteration) {
    isDisplayStep =
        (displayIteration > 0 && ((step + 1) % displayIteration == 0))
    val result = helper?.execute(isDisplayStep)

    if (isDisplayStep) {
        _uiState.update {
            it.copy(
                outputBitmap = result,
                generatingMessage = "Generating... (${step + 1}/$iteration)",
            )
        }
    }
}

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

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

إلى جانب نسخ الملفات مباشرةً إلى جهاز التطوير، من الممكن أيضًا إعداد مساحة تخزين Firebase لتنزيل الملفات الضرورية مباشرةً على جهاز المستخدم أثناء التشغيل.

5- نشر التطبيق واختباره

بعد كل ذلك، يُفترض أن يكون لديك تطبيق صالح يمكنه قبول الطلبات النصية وإنشاء صور جديدة بالكامل على الجهاز فقط. انطلق وانشر التطبيق على جهاز Android فعلي لاختباره، ولكن تذكر أنك ستحتاج إلى تجربة هذا على جهاز يحتوي على ذاكرة لا تقل عن 8 غيغابايت.

  1. انقر على "تشغيل" (7e15a9c9e1620fe7.png) في شريط أدوات "استوديو Android" لتشغيل التطبيق.
  2. اختَر نوع خطوات الإنشاء (نهائي أو مع تكرارات) ثم اضغط على الزر بدء.
  3. على الشاشة التالية، عيِّن أي خصائص تريدها وانقر على الزر إنشاء للاطلاع على الأداة.

e46cfaeb9d3fc235.gif

6- تهانينا

أحسنت. لقد تعلّمت في هذا الدرس التطبيقي كيفية إضافة ميزة "تحويل النص إلى صورة" على الجهاز إلى تطبيق Android.

الخطوات التالية

وهناك المزيد الذي يمكنك تنفيذه من خلال مهمة إنشاء الصور، مثل

  • استخدام صورة أساسية لإنشاء صور من إنشاء المكوّنات الإضافية، أو تدريب أوزان LoRA الإضافية من خلال Vertex AI
  • استخدم مساحة تخزين Firebase لاسترداد ملفات النماذج على جهازك بدون الحاجة إلى استخدام أداة ADB.

نتطلّع إلى رؤية كل الميزات الرائعة التي ستنشئها من خلال هذه المهمة التجريبية، وننتظر منك المزيد من الدروس التطبيقية حول الترميز والمحتوى من فريق MediaPipe.