إنشاء أول تطبيق Vision على نظام التشغيل Android أو iOS

1. قبل البدء

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

المتطلّبات الأساسية

يُعد هذا الدرس التطبيقي جزءًا من مسار البدء في تصنيف الصور. وقد صُممت مطوّري البرامج ذوي الخبرة في مجال تكنولوجيا تعلّم الآلة.

العناصر التي سيتم إنشاؤها

  • تطبيق Android قادر على تصنيف صورة زهرة
  • (اختياري) تطبيق iOS قادر على تصنيف صورة زهرة

الأشياء التي تحتاج إليها

  • Android Studio متوفّر على https://developer.android.com/studio لجزء Android من Codelab
  • Xcode الذي يتوفر في Apple App Store للجزء الذي يعمل بنظام التشغيل iOS من Codelab

2. البدء

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

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

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

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

ستبدأ من خلال عملية إنشاء التطبيق على Android باستخدام "استوديو Android". (انتقل إلى الخطوة 7 لإجراء ما يعادل ذلك على نظام التشغيل iOS.)

  1. افتح "استوديو Android" وانتقِل إلى القائمة "ملف" واختَر "إنشاء مشروع جديد".
  2. سيُطلب منك اختيار نموذج مشروع. انقر على "نشاط فارغ".

859b1875e37c321a.png

  1. انقر على التالي. سيُطلب منك ضبط مشروعك. امنحه أي اسم أو اسم حزمة تريده، ولكن يستخدم نموذج الرمز في هذا الدرس التطبيقي اسم المشروع ImageClassifierStep1 واسم الحزمة com.google.imageclassifierstep1.

ee3b6a81bad87b3.png

  1. اختَر لغتك المفضّلة، إما لغة Kotlin أو Java. يستخدم هذا الدرس التطبيقي لغة Kotlin، لذا إذا كنت تريد المتابعة بالطريقة نفسها، ربما تحتاج إلى اختيار لغة Kotlin.
  2. عندما تكون مستعدًا، انقر على "إنهاء". سيُنشئ تطبيق "استوديو Android" التطبيق من أجلك. قد يستغرق إعداد كل شيء بضع لحظات.

3- استيراد مكتبة تصنيف الصور ML Kit

توفّر حزمة تعلُّم الآلة (https://developers.google.com/ml-kit) عددًا من الحلول لمطوّري البرامج، حيث تُلبي السيناريوهات الشائعة في تعلُّم الآلة وتُسهِّل تنفيذها والعمل من خلال عدّة منصات. توفّر مجموعة أدوات تعلّم الآلة مكتبة مفاتيح يمكنك استخدامها في هذا التطبيق يُسمى "تصنيف الصور". تتضمن هذه المكتبة نموذجًا تم تدريبه مسبقًا للتعرّف على أكثر من 600 فئة من الصور. وبذلك، يمكنك بدء استخدام التطبيق.

لاحظ أن ML Kit يتيح لك أيضًا استخدام نماذج مخصصة باستخدام واجهة برمجة التطبيقات نفسها، ولذلك عندما تكون مستعدًا، يمكنك تجاوز حدود "البدء"&وبدء الخطوات الأولى وإنشاء تطبيق مخصص لتصنيف الصور يستخدم نموذجًا تم تدريبه للسيناريو.

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

  1. في "استوديو Android"، باستخدام مستكشف المشاريع، تأكّد من اختيار Android في أعلى الصفحة.
  2. افتح مجلد Gradle Scripts، واختر ملف build.gradle للتطبيق. قد يكون هناك ملفان أو أكثر، لذا يجب التأكّد من استخدام مستوى التطبيق كما هو موضّح هنا:

93c2e157136671aa.png

  1. في أسفل الملف، سيظهر لك قسم بعنوان العناصر التابعة حيث يتم تخزين قائمة implementation وtestImplementation وandroidImplementation. إضافة رمز جديد إلى الملف باستخدام الرمز التالي:
implementation 'com.google.mlkit:image-labeling:17.0.3'

(يجب استخدام رمز التبعيّات { })

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

5ef40c7a719077a0.png

لقد قمت الآن باستيراد مجموعة تعلّم الآلة، وأنت مستعد لبدء تصنيف الصور.

بعد ذلك، ستنشئ واجهة مستخدم بسيطة لعرض صورة، وستعطيك زرًا عند الضغط على المستخدم، تستدعي ML Kit نموذج تصنيف الصورة لتحليل محتوى الصورة.

4. إنشاء واجهة المستخدم

في "استوديو Android"، يمكنك تعديل واجهة المستخدم لكل شاشة (أو النشاط) باستخدام ملف تنسيق مستند إلى xml. يحتوي التطبيق الأساسي الذي أنشأته على نشاط واحد (رمزه في MainActivity، وسترى ذلك قريبًا)، وسيظهر إعلان واجهة المستخدم في activity_main.xml.

يمكنك العثور عليه في مجلد res >Layout في مستكشِف مشاريع Android's – على النحو التالي:

3ed772e9563061e9.png

سيؤدّي ذلك إلى فتح محرِّر كامل يتيح لك تصميم واجهة مستخدم نشاطك. هناك الكثير، ولن يكون الهدف من هذا الدرس التطبيقي هو تعليمك كيفية استخدامه. لمزيد من المعلومات عن محرر التنسيقات، يُرجى زيارة https://developer.android.com/studio/write/Layout-editor.

لأغراض هذا الدرس التطبيقي، اختَر أداة الرموز في أعلى يسار شاشة المحرّر.

1f7dbdef48d9ade6.png

سترى الآن رمز XML في الجزء الرئيسي من النافذة. غيِّر الرمز إلى ما يلي:

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity">

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="vertical"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent">

        <ImageView
            android:id="@+id/imageToLabel"
            android:layout_width="match_parent"
            android:layout_height="match_parent" />
        <Button
            android:id="@+id/btnTest"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="Label Image"
            android:layout_gravity="center"/>
        <TextView
            android:id="@+id/txtOutput"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:ems="10"
            android:gravity="start|top" />
    </LinearLayout>
</androidx.constraintlayout.widget.ConstraintLayout>

يمنحك هذا تنسيقًا بسيطًا للغاية يتضمّن ImageView (لعرض الصورة) وButton ( ليضغط عليها المستخدم) وTextView حيث سيتم عرض التصنيفات.

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

5. تجميع الصور مع التطبيق

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

  1. في مستكشف المشاريع، على التطبيق في أعلى الصفحة، انقر بزر الماوس الأيمن واختَر "دليل جديد".
  2. في مربع الحوار الذي يظهر مع قائمة أدلة مختلفة، حدد src/main/assets.

C93650ea68bb60e9.png

بعد الانتهاء من ذلك، سيظهر لك مجلد مواد عرض جديد في مستكشف المشروع:

444b4afab73433b8.png

  1. انقر بزر الماوس الأيمن على هذا المجلد، وستظهر لك نافذة منبثقة تحتوي على قائمة بالخيارات. وستكون إحدى هذه الخطوات هي فتح المجلد في نظام الملفات. ابحث عن التطبيق المناسب لنظام التشغيل وحدده. (على أجهزة Mac، سيكون هذا الإعداد هو Reveal in Finder (الباحث) في Windows، وسيكون القسم Open in Explorer (فتح في Explorer)، أما على Ubuntu، سيكون Show in Files (عرض في الملفات).)

95e0eca881d35f6b.png

  1. انسخ ملفًا فيه. يمكنك تنزيل الصور من مواقع مثل Pixaباي. يُوصى بإعادة تسمية الصورة إلى عنصر بسيط. وفي هذه الحالة، تمت إعادة تسمية الصورة flower1.jpg.

بعد الانتهاء من ذلك، ارجع إلى "استوديو Android"، ويُفترض أن يظهر لك ملفك في مجلد "مواد العرض".

cfa53c9c75a033d8.png

أنت الآن جاهز لتصنيف هذه الصورة.

6- كتابة رمز التصنيف لتصنيف الصورة

(والآن، الجزء الذي كنا ننتظره متاحًا، حيث ننشئ الكمبيوتر الحاسوبي على Android.)

  1. ستكتب الرمز في ملف MainActivity، لذا ابحث عنه في مجلد المشروع ضمن com.google.devrel.imageclassifierstep1 (أو أي مساحة اسم مماثلة في حال اختَرت مساحة اسم مختلفة). تجدر الإشارة إلى أنه تم إعداد 3 مجلدات لمساحة الاسم بشكل عام في مشروع في استوديو Android، واحد للتطبيق، والآخر لـ Android Test، وآخر للاختبار. ستجد MainActivity في الوصف الذي لا يتضمن وصفًا بعده بين قوسين.

b5aef8dd5e26b6c2.png

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

  1. افتح الملف MainActivity، وسيظهر لك ملف صف باسم MainActivity في أداة تعديل الرموز. ومن المفترض أن يظهر الرقم بالشكل التالي:
class MainActivity : AppCompatActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
    }
}

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

  1. إضافة هذا الرمز:
// extension function to get bitmap from assets
fun Context.assetsToBitmap(fileName: String): Bitmap?{
    return try {
        with(assets.open(fileName)){
            BitmapFactory.decodeStream(this)
        }
    } catch (e: IOException) { null }
}

من المحتمل أن يشكّل Android Studio شكوى في هذه المرحلة، ويسلط الضوء على بعض الرموز باللون الأحمر، مثل Context وBitmap وIOException:

d2bde17e3c04aeed.png

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

  1. اسحب المؤشر فوق الكلمة، واضغط على Alt + Enter (Option + Enter في Mac) وسيتم إنشاء الاستيراد لك.
  2. ويمكنك بعد ذلك تحميل الصورة النقطية من مواد العرض ووضعها في ImageView. في onCreateFunction من MainActivity، أضف هذا الرمز أسفل سطر setContentView مباشرةً:
val img: ImageView = findViewById(R.id.imageToLabel)
// assets folder image file name with extension
val fileName = "flower1.jpg"
// get bitmap from assets folder
val bitmap: Bitmap? = assetsToBitmap(fileName)
bitmap?.apply {
    img.setImageBitmap(this)
}
  1. وكما في السابق، سيتم تمييز بعض الرموز باللون الأحمر. ضع المؤشر على هذا السطر واستخدِم Alt + Enter / Option + Enter لإضافة عمليات الاستيراد تلقائيًا.
  2. في ملف layout.xml الذي أنشأته سابقًا، منحت ImageView اسم imageToLabel، لذا سينشئ السطر الأول مثيلاً من عنصر ViewView، يُسمى img، باستخدام معلومات التنسيق هذه. يعثر على التفاصيل باستخدام findViewById، وهي وظيفة مدمجة في Android. وتستخدم بعد ذلك اسم الملف flower1.jpg لتحميل صورة من مجلد مواد العرض باستخدام الدالة assetsToBitmap التي أنشأتها في الخطوة السابقة. وأخيرًا، تستخدم الأداة صورة نقطية مجردة لتحميل صورة نقطية في img.
  3. يحتوي ملف التنسيق على TextView سيتم استخدامه لعرض التصنيفات التي تم استنتاجها للصورة. احصل على كائن رمز لتنفيذ ذلك في الخطوة التالية. أسفل الرمز السابق مباشرةً، أضِف ما يلي:
val txtOutput : TextView = findViewById(R.id.txtOutput)

كما في السابق، يؤدي ذلك إلى العثور على معلومات ملف التنسيق للعرض النصي باستخدام اسمه (تحقّق من XML حيث يكون اسمه txtOutput) ويستخدمه لإنشاء كائن TextView باسم txtOutput.

وبالمثل، عليك إنشاء كائن زر لتمثيل الزر، وإنشاء مثيل له باستخدام محتوى ملف التنسيق.

في ملف التنسيق، أنشأنا الزر btnTest، لنتمكّن من إنشاء مثيل له على النحو التالي:

val btn: Button = findViewById(R.id.btnTest)

الآن بعد إعداد كل عناصر التحكّم والرمز، ستكون الخطوة التالية (والنهائية) هي استخدامها لاستنتاج الصورة.

قبل المتابعة، تأكّد من أن رمز onCreate يظهر على النحو التالي:

override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    setContentView(R.layout.activity_main)
    val img: ImageView = findViewById(R.id.imageToLabel)
    // assets folder image file name with extension
    val fileName = "flower1.jpg"
    // get bitmap from assets folder
    val bitmap: Bitmap? = assetsToBitmap(fileName)
    bitmap?.apply {
        img.setImageBitmap(this)
    }
    val txtOutput : TextView = findViewById(R.id.txtOutput)
    val btn: Button = findViewById(R.id.btnTest)
}

يجب ألا يكون لون أي من الكلمات الرئيسية باللون الأحمر، ما يشير إلى أنها لم يتم استيرادها بعد. إذا كانت كذلك، يُرجى الرجوع وإجراء خدعة Alt + Enter لإنشاء عمليات الاستيراد.

عند استخدام أداة تصنيف الصور ML Kit's، تتمثل الخطوة الأولى عادةً في إنشاء كائن خيارات لتخصيص السلوك. ستتمكّن من تحويل صورتك إلى تنسيق InputImage الذي تتعرّف عليه حزمة ML. بعد ذلك، يمكنك إنشاء عنصر Label لإجراء الاستنتاج. سيعيد الاتصال باستدعاء غير متزامن مع النتائج التي يمكنك تحليلها.

على الزر الذي أنشأته للتو، يمكنك تنفيذ كل ذلك ضمن حدث onClickListener. هذا هو الرمز الكامل:

btn.setOnClickListener {
  val labeler = ImageLabeling.getClient(ImageLabelerOptions.DEFAULT_OPTIONS)
  val image = InputImage.fromBitmap(bitmap!!, 0)
  var outputText = ""
  labeler.process(image)
    .addOnSuccessListener { labels ->
      // Task completed successfully
      for (label in labels) {
        val text = label.text
        val confidence = label.confidence
        outputText += "$text : $confidence\n"
      }
      txtOutput.text = outputText
  }
    .addOnFailureListener { e ->
      // Task failed with an exception
  }
}
  • عندما ينقر المستخدم لأول مرة على الزر، ستنشئ الرمز مثيلًا لـ VideoLabel يأتي ذلك مع خاصية DEFAULT_OPTIONS تتيح لنا بدء العمل بسرعة.
  • بعد ذلك، سيتم إنشاء InputImage من الصورة النمطية باستخدام طريقة Bitmap. الإدخال المصوّر هو تنسيق ML Kit\u30s المرغوب في معالجة الصور.
  • وأخيرًا، سيعمل "المُصنِّف" على معالجة الصورة وتقديم استدعاء غير متزامن، سواء بنجاح أو عند الإخفاق. إذا كان الاستنتاج ناجحًا، ستتضمن معاودة الاتصال قائمة بالتصنيفات. يمكنك بعد ذلك تحليل قائمة التصنيفات هذه لقراءة نص التصنيف وقيمة الثقة. وفي حال إخفاق ذلك، سيؤدي ذلك إلى إعادتك إلى استثناء يمكنك استخدامه للإبلاغ عن ذلك المستخدم.

وهكذا انتهى كل شيء! يمكنك الآن تشغيل التطبيق إما على جهاز Android أو داخل المحاكي. إذا لم تكن قد فعلت ذلك من قبل، يمكنك التعرّف على كيفية إجراء ذلك هنا: https://developer.android.com/studio/run/emulator

هذا هو التطبيق الذي يتم تشغيله في المحاكي. سترى أولاً الصورة والزر، وسيكون التصنيف فارغًا.

c07f5f307f070dc7.png

اضغط على الزر، وستحصل على مجموعة من التصنيفات للصورة.

550ccaa783363551.png

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

ولكن لا يمكنها بعد تحديد ما إذا كانت هذه صورة إقحوان. ولتحقيق هذا الغرض، ستحتاج إلى نموذج مخصّص يتم تدريبه على زهور معيّنة، وستتعرّف على كيفية تنفيذ ذلك في الدرس التالي.

في الخطوات التالية، ستستكشف كيفية إنشاء هذا التطبيق نفسه على iOS.

7- إنشاء أداة تصنيف صور على iOS - البدء

يمكنك إنشاء تطبيق مماثل على iOS باستخدام Xcode.

  1. شغّل Xcode، ومن قائمة الملف، اختر مشروع جديد. سيظهر لك مربع الحوار هذا:

8fb0e6a9d6ac275e.png

  1. اختَر التطبيق كما هو موضّح، وانقر على التالي. سيُطلب منك تحديد خيارات مشروعك. امنحه اسمًا ومعرّف مؤسسة كما هو موضح. تأكَّد من أنّ نوع الواجهة هو Storyboard، وأنّ اللغة هي Swift كما هو موضّح.

76c6bdb5aee7659c.png

  1. إذا كنت تريد النشر على هاتف وإعداد ملف شخصي لمطوّر برامج، يمكنك ضبط إعداد فريقك. إذا لم يكن الأمر كذلك، اترُك هذا الخيار على بدون ويمكنك استخدام محاكي iOS لتشغيل تطبيقك.
  2. انقر على Next (التالي) واختَر مجلدًا لتخزين مشروعك وملفاته. تذكر موقع هذا المشروع، ستحتاج إليه في الخطوة التالية.
  3. أغلِق Xcode في الوقت الحالي، لأنك ستعيد فتحه باستخدام ملف مساحة عمل مختلف بعد الخطوة التالية.

8- دمج حزمة تعلّم الآلة باستخدام Cocoapods

وبما أنّ حزمة تعلّم الآلة تعمل أيضًا على نظام التشغيل iOS، يمكنك استخدامها بطريقة مشابهة جدًا لإنشاء أداة تصنيف صور. لدمجه، يجب استخدام CocoaPods. إذا لم يكن هذا التطبيق مثبتًا لديك، يمكنك إجراء ذلك من خلال التعليمات الواردة في https://cocoapods.org/

  1. افتح الدليل الذي أنشأت فيه مشروعك. يجب أن يحتوي هذا الملف على ملف .xcodeenterprise.

يمكنك هنا الاطّلاع على ملف .xcodeproject الذي يشير إلى I'm في المكان الصحيح.

e2966a47e84eb398.png

  1. في هذا المجلد، أنشِئ ملفًا جديدًا باسم Podfile. لا توجد امتدادات، بل ملف Podfile. وضمنه، أضِف ما يلي:
platform :ios, '10.0'

target 'ImageClassifierStep1' do
        pod 'GoogleMLKit/ImageLabeling'
end
  1. احفظ البطاقة وعُد إلى الوحدة الطرفية. في النوع نفسه للدليل pod install. سيعمل Cocoapods على تنزيل المكتبات والتبعيات المناسبة وإنشاء مساحة عمل جديدة تجمع مشروعك بالارتباطات الخارجية.

3b4c628b0cbface8.png

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

32090e0024b6b5ef.png

أنت الآن على استعداد للانتقال إلى الخطوة التالية وإنشاء واجهة المستخدم.

9- إنشاء واجهة مستخدم iOS باستخدام لوحات العمل

  1. افتح ملف Main.storyboard وسيرى تنسيق واجهة مستخدم بسطح تصميم للهاتف.
  2. في أعلى يسار الشاشة، هناك زر + يمكنك استخدامه لإضافة عناصر التحكُّم. انقر عليه للحصول على لوحة التحكم.

e63bc3bafa54cc21.png

  1. ومن هناك، اسحب ImageView وزر وتصنيف إلى سطح التصميم وأفلِته. يمكنك ترتيبها من الأعلى إلى الأسفل كما هو موضّح أدناه:

f9dfc55616b25f11.png

  1. انقر مرّتين على الزر لتعديل نصه من الزر إلى تصنيف.
  2. اسحب مقابض التحكم حول التصنيف لتكبيره. (على سبيل المثال، قلّل عرض UIImageView وضعف نفس الارتفاع.)
  3. بعد اختيار التصنيف، انقر على الزر المحدِّدات في أعلى يسار الصفحة لعرض لوحة أدوات الفحص.
  4. بعد الانتهاء من ذلك، ابحث عن إعداد الخطوط وتأكّد من ضبطه على 0. ويسمح ذلك للتصنيف بعرض عدد ديناميكي من الأسطر.

a39708b320b56b30.png

أنت مستعد الآن لاتخاذ الخطوة التالية، عليك توصيل واجهة المستخدم بالترميز باستخدام المنافذ والإجراءات.

10- إنشاء إجراءات ومنافذ

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

في الخطوة التالية، ستحتاج إلى إنشاء منافذ لـ ImageView والتصنيف. وستتم الإشارة إلى الصورة في الرمز لتحميل الصورة إليها. ستتم الإشارة إلى التصنيف في الرمز لضبط النص استنادًا إلى الاستنتاجات التي تعود من ML Kit.

  1. وأغلق لوحة المفتشين من خلال النقر على عنصر التحكم في أعلى يسار الشاشة، ثم النقر على زر إضافة محرر على اليمين أسفله مباشرةً.

77255f7d6284750.png

  1. سيكون لديك تنسيق شاشة مربك حيث يتم فتح main.storyboard مرتين. على يمين الصفحة، في متصفِّح المشروع، اختَر ViewController.swift لكي يتم فتح رمز وحدة التحكم في العرض. يبدو أن سطح التصميم قد اختفى من محرّر لوحات العمل على اليمين، ولكن لا داعي للقلق، فرغم ذلك لا يزال متوفرًا.
  2. ولاسترداده، انقر على عرض وحدة التحكم في منظر عرض وحدة التحكم. جرِّب جعل واجهة المستخدم تبدو بالشكل التالي، مع لوحة العمل على اليمين التي تعرض تصميمك والرمز الخاص بـ ViewController.swift على اليسار.

7eb21c7f9d43c9bc.png

  1. اختَر UIImageView من سطح التصميم على اليمين، وأثناء الضغط على مفتاح Control، اسحبه إلى الرمز على اليسار، وأفلته أسفل الكلمة الرئيسية class مباشرةً (في السطر 11 في لقطة الشاشة أعلاه).

سيظهر لك سهم أثناء السحب، وعند إفلاتك، ستظهر لك نافذة منبثقة كما يلي:

37477f0611948318.png

  1. املأ حقل الاسم كـ "imageView" وانقر على اتصال.
  2. كرر هذه العملية مع التصنيف وامنحه الاسم "lblOutput&"
  3. ملاحظة مهمة: بالنسبة إلى الزر، ستنفّذ الإجراء نفسه، ولكن احرِص على ضبط نوع الاتصال على Action وليس Outlet.

7281b6eea9fb6c23.png

  1. أدخِل الاسم "doClassification" وانقر على Connect (ربط).

وعند الانتهاء، يجب أن يظهر الرمز كما يلي: (لاحظ أنه يتم عرض التصنيف والعرض للصورة على أنه IBOutlet (مقبس واجهة الواجهة) والزر على أنه إعلان IBA وصول (إجراء إنشاء واجهة).

import UIKit

class ViewController: UIViewController {

    @IBAction func doClassification(_ sender: Any) {
    }
    @IBOutlet weak var imageView: UIImageView!
    @IBOutlet weak var lblOutput: UILabel!
    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view.
    }

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

889ff33eaec785ec.png

  1. تأكّد من وضع علامة في مربّع الاختيار في قسم إضافة إلى الأهداف كما هو موضّح، ثم انقر على إنهاء.

سيتم تجميع الملف مع تطبيقك، ويمكنك الآن تصنيفه بسهولة. أنت الآن على استعداد لترميز واجهة المستخدم لتصنيف الصور.

11- كتابة الرمز لتصنيف الصور

الآن بعد أن تم إعداد كل شيء، أصبحت كتابة الرمز لإجراء تصنيف الصورة مباشرةً حقًا.

  1. ابدأ بإغلاق مصمّم لوحة العمل بالنقر على الرمز X في أعلى يمين الشاشة فوق سطح التصميم. وهذا يتيح لك التركيز على الرمز فقط. ستكون عليك تعديل ViewController.swift لبقية هذا الدرس التطبيقي.
  2. يمكنك استيراد مكتبات MLKitVision وMLKit ImageLabeling عن طريق إضافة هذا الرمز في أعلى الصفحة، أسفل استيراد UIKit:
import MLKitVision
import MLKitImageLabeling
  1. وبعد ذلك، ضمن دالة viewDidLoad، عليك إعداد ImageView باستخدام الملف الذي تم تجميعه في التطبيق:
override func viewDidLoad() {
    super.viewDidLoad()
    // Do any additional setup after loading the view.
    imageView.image = UIImage(named:"flower1.jpg")
}
  1. أنشئ وظيفة مساعدة للحصول على تصنيفات الصورة، أسفل viewDidLoad() مباشرةً:
func getLabels(with image: UIImage){
  1. أنشئ صورة VisionImage من الصورة. تستخدم حزمة تعلُّم الآلة هذا النوع عند إجراء تصنيف الصور. لذلك، أضِف الرمز التالي ضمن وظيفة getLabel:
let visionImage = VisionImage(image: image)
visionImage.orientation = image.imageOrientation
  1. بعد ذلك، أنشئ خيارات تصنيف الصورة. وسيتم إعداده باستخدام هذه الخيارات. في هذه الحالة، عليك فقط تحديد خيار أساسي من confidenceThreshold. وهذا يعني أنك لن تطلب من التصنيف سوى عرض التصنيفات التي لا تثق فيها بمقدار 0.4 أو أعلى. على سبيل المثال، بالنسبة إلى زهرةنا، ستكون للفئات مثل "&&;النبات&";&;;&;;petal" ثقة كبيرة أم لا, مثل البعض الآخر&";كرة السلة"&أو "&";العربات"
let options = ImageLabelerOptions()
options.confidenceThreshold = 0.4
  1. يمكنك الآن إنشاء التصنيف باستخدام الخيارات التالية:
let labeler = ImageLabeler.imageLabeler(options: options)
  1. وبعد الحصول على التصنيف، يمكنك معالجته. سيوفر لك هذا الإجراء معاودة اتصال غير متزامنة مع التصنيفات (إذا نجح ذلك) وخطأ (إذا فشل ذلك)، فإنه يمكنك بعد ذلك معالجته في وظيفة أخرى سننشئها خلال لحظات.
labeler.process(visionImage) { labels, error in
    self.processResult(from: labels, error: error)
  }

لا داعي للقلق إذا اشتكت Xcode من عدم وجود عضو في processResult. لم تنفِّذ ذلك بعد، وستنفّذ ذلك بعد ذلك.

ولتسهيل الأمر، نقدّم لك هنا طريقة الحصول على التصنيفات الكاملة:

// This is called when the user presses the button
func getLabels(with image: UIImage){
    // Get the image from the UI Image element and set its orientation
    let visionImage = VisionImage(image: image)
    visionImage.orientation = image.imageOrientation

    // Create Image Labeler options, and set the threshold to 0.4
    // so we will ignore all classes with a probability of 0.4 or less
    let options = ImageLabelerOptions()
    options.confidenceThreshold = 0.4

    // Initialize the labeler with these options
    let labeler = ImageLabeler.imageLabeler(options: options)

    // And then process the image, with the callback going to self.processresult
    labeler.process(visionImage) { labels, error in
        self.processResult(from: labels, error: error)
 }
}

لذلك عليك الآن تنفيذ الدالة processResult. وهذا الأمر بسيط جدًا في الوقت الحالي، بما أنّه لدينا تصنيفات و الكائن الذي يعرض خطأ. ويجب إرسال التصنيفات إلى النوع ImageLabel من ML Kit.

وبعد الانتهاء من ذلك، يمكنك ببساطة تكرار مجموعة التصنيفات وسحب الوصف وقيمة الثقة وإضافتها إلى var باسم labeltexts. وبعد تكرارها جميعًا، ما عليك سوى ضبط lblOutput.text على تلك القيمة.

وإليك الدالة الكاملة:

// This gets called by the labeler's callback
func processResult(from labels: [ImageLabel]?, error: Error?){
    // String to hold the labels
    var labeltexts = ""
    // Check that we have valid labels first
    guard let labels = labels else{
        return
    }
  // ...and if we do we can iterate through the set to get the description and confidence
    for label in labels{
        let labelText = label.text + " : " + label.confidence.description + "\n"
        labeltexts += labelText
    }
    // And when we're done we can update the UI with the list of labels
    lblOutput.text = labeltexts
}

كل ما يتبقى هو الاتصال بـ getLabels عندما يضغط المستخدم على الزر.

عندما أنشأت الإجراء، تم دمج كل البيانات من أجلك، لذلك ما عليك سوى تحديث IBAction التي تُسمى doClassificaiton والتي أنشأتها سابقًا للاتصال بـ getLabels.

هنا الرمز الذي يجب استدعاءه باستخدام محتوى imageView:

@IBAction func doClassification(_ sender: Any) {
    getLabels(with: imageView.image!)
}

شغِّل تطبيقك الآن وجرِّبه. يمكنك الاطّلاع على أمثلة واقعية على ذلك:

eb8e6c1b2e2c65e0.png

لاحظ أن التنسيق قد يبدو مختلفًا حسب جهازك.

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

مع تطوير المزيد من المعلومات عن تطوير تطبيقات iOS، ستتعرّف على كيفية استخدام القيود للتأكّد من اتساق واجهة المستخدم على الهواتف، غير أنّها تتجاوز نطاق هذا الدرس التطبيقي.

12- تهانينا.

لقد نفّذت الآن تطبيقًا على كل من نظامَي التشغيل Android وiOS يمنحك رؤية أساسية لجهاز الكمبيوتر من خلال نموذج عام. لقد أنجزت معظم المهام الثقيلة بالفعل.

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