تحليل الصور

تحليل الصور أنّ حالة الاستخدام توفّر لتطبيقك صورة يمكن الوصول إليها من خلال وحدة المعالجة المركزية (CPU) يمكنك من خلالها تنفيذ معالجة الصور، أو الرؤية الحاسوبية، أو استنتاج التعلم الآلي. تشير رسالة الأشكال البيانية أحد التطبيقات analyze() يتم تشغيله على كل إطار.

للتعرّف على كيفية دمج حزمة تعلُّم الآلة من Google مع تطبيق CameraX، اتّبِع الخطوات التالية: يُرجى الاطّلاع على أداة تحليل حزمة تعلّم الآلة.

أوضاع التشغيل

عندما يتعذر على مسار تحليل التطبيق مواكبة إطار CameraX لمعدل عرض الإطارات، يمكن تهيئة CameraX على إسقاط الإطارات بإحدى الطرق التالية:

  • غير محظورة (تلقائي): في هذا الوضع، يخزِّن القائم بالتنفيذ دائمًا ذاكرة التخزين المؤقت أحدث صورة في المخزن المؤقت للصور (يشبه قائمة انتظار بعمق صورة واحدة) بينما يحلل التطبيق الصورة السابقة إذا كان تطبيق CameraX صورة جديدة قبل انتهاء معالجة التطبيق، جديدة في نفس المخزن المؤقت، وستحل محل الصورة السابقة. يُرجى العِلم أنّ ImageAnalysis.Builder.setImageQueueDepth() ليس له أي تأثير في لهذا السيناريو، ويتم دائمًا استبدال محتويات المخزن المؤقت. يمكنك تفعيل وضع عدم الحظر هذا عن طريق استدعاء setBackpressureStrategy() باستخدام STRATEGY_KEEP_ONLY_LATEST لمزيد من المعلومات حول تداعيات جهة التنفيذ، يُرجى الاطّلاع على المرجع وثائق STRATEGY_KEEP_ONLY_LATEST

  • الحظر: في هذا الوضع، يمكن لأداة التنفيذ الداخلي إضافة صور متعددة. إلى قائمة انتظار الصور الداخلية ويبدأ في إسقاط الإطارات فقط عندما تكون قائمة الانتظار ممتلئة. يحدث الحظر على مستوى جهاز الكاميرا بالكامل: إذا كانت لجهاز الكاميرا هذا يتضمن حالات استخدام متعددة مرتبطة، سيتم حذف جميع هذه الحالات أثناء معالجة CameraX لهذه الصور. بالنسبة عند ربط كل من المعاينة وتحليل الصور بجهاز كاميرا، فسيتم أيضًا حظر المعاينة أثناء معالجة CameraX للصور. يمكنك تفعيل "وضع الحظر" من خلال تمرير STRATEGY_BLOCK_PRODUCER إلى setBackpressureStrategy() يمكنك أيضًا ضبط عمق قائمة انتظار الصور باستخدام ImageAnalysis.Builder.setImage playlistDepth():

ومع وقت الاستجابة البطيء ومحلل الأداء العالي، يمكن أن يكون الوقت الإجمالي تحليل صورة أقل من مدة إطار CameraX. (على سبيل المثال، 16 مللي ثانية مقابل 60 لقطة في الثانية)، يوفر أي من وضعي التشغيل تجربة المستخدم. لا يزال وضع الحظر مفيدًا في بعض السيناريوهات، مثل عند التعامل مع حالات قلق بسيطة جدًا في النظام.

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

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

التنفيذ

لاستخدام تحليل الصور في تطبيقك، اتّبِع الخطوات التالية:

ترسل CameraX الصور إلى أداة التحليل المسجلة لك مباشرةً بعد الربط. بعد الانتهاء من التحليل، اتصل ImageAnalysis.clearAnalyzer() أو إلغاء ربط حالة الاستخدام ImageAnalysis لإيقاف التحليل.

إنشاء حالة الاستخدام لتحليل الصور

اتصال ImageAnalysis أداة التحليل (مستهلك للصور) إلى CameraX، وهي منتج للصور. يمكن للتطبيقات استخدام ImageAnalysis.Builder لإنشاء كائن ImageAnalysis. باستخدام ImageAnalysis.Builder، تطبيقك تهيئة ما يلي:

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

يمكن لأحد التطبيقات ضبط وحدات بكسل صورة الإخراج لتكون في YUV (تلقائي) أو RGBA. عند ضبط تنسيق إخراج RGBA، يجب استخدام CameraX داخليًا. لتحويل الصور من YUV إلى مساحة لون RGBA ووضع وحدات بت الصور في ByteBuffer للطائرة الأولى ImageProxy (لا يتم استخدام الطائرتين الأخريين) مع التسلسل التالي:

ImageProxy.getPlanes()[0].buffer[0]: alpha
ImageProxy.getPlanes()[0].buffer[1]: red
ImageProxy.getPlanes()[0].buffer[2]: green
ImageProxy.getPlanes()[0].buffer[3]: blue
...

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

إنشاء أداة التحليل

يمكن للتطبيقات إنشاء أدوات تحليل من خلال تنفيذ ImageAnalysis.Analyzer الواجهة وتجاوز analyze(ImageProxy image) في كل محلل، تتلقى التطبيقات ImageProxy، وهو برنامج تضمين في Media.Image يمكن الاستعلام عن تنسيق الصورة باستخدام ImageProxy.getFormat() يُعد التنسيق إحدى القيم التالية التي يستخدمها التطبيق مع ImageAnalysis.Builder:

  • ImageFormat.RGBA_8888 إذا طلب التطبيق مبلغ OUTPUT_IMAGE_FORMAT_RGBA_8888.
  • ImageFormat.YUV_420_888 إذا طلب التطبيق مبلغ OUTPUT_IMAGE_FORMAT_YUV_420_888.

يُرجى الاطّلاع على حالة استخدام تحليل الصور (Build ImageAnalysis). للتعرّف على إعدادات مساحة الألوان والمكان الذي يمكن فيه استرداد وحدات بايت البكسل.

داخل المحلل، يجب أن يقوم التطبيق بما يلي:

  1. قم بتحليل إطار معين بأسرع وقت ممكن، ويفضل أن يكون ذلك داخل الإطار وفقًا للحد الزمني لعدد اللقطات في الثانية (على سبيل المثال، أقل من 32 ملي ثانية للحالة 30 لقطة في الثانية). وإذا لم يتمكن التطبيق من تحليل إطار بسرعة كافية، ننصحك أحد آليات إسقاط الإطارات المتوافقة.
  2. ارفع إصبعك عن ImageProxy إلى CameraX من خلال الاتصال. ImageProxy.close() لاحظ أنه يجب عدم استدعاء دالة إغلاق Media.Image (Media.Image.close()).

ويمكن للتطبيقات استخدام عنصر Media.Image الملفوف داخل ImageProxy مباشرةً. فقط لا تطلب Media.Image.close() على الصورة الملتفّة لأنّ ذلك قد ينكسر. آلية مشاركة الصور داخل CameraX؛ بدلاً من ذلك، استخدم ImageProxy.close() لإطلاق Media.Image الأساسية إلى CameraX.

إعداد أداة التحليل لتحليل الصور

بمجرد إنشاء محلل، استخدم ImageAnalysis.setAnalyzer() لتسجيله لبدء التحليل. بمجرد الانتهاء من التحليل، استخدم ImageAnalysis.clearAnalyzer() لإزالة أداة التحليل المسجلة.

يمكن ضبط أداة تحليل نشطة واحدة فقط لتحليل الصور. إجراء المكالمات يحل ImageAnalysis.setAnalyzer() محل المحلل المسجَّل إذا كان الموجودة. يمكن للتطبيقات تعيين أداة تحليل جديدة في أي وقت، قبل الربط أو بعده في حالة الاستخدام.

ربط تحليل الصور بدورة حياة

ننصح بشدة بربط "ImageAnalysis" بجهاز حالي. دورة حياة AndroidX من خلال ProcessCameraProvider.bindToLifecycle() الأخرى. لاحظ أن الدالة bindToLifecycle() تعرض القيم المحددة جهاز Camera يمكن استخدامه لضبط الإعدادات المتقدمة مثل التعرض للضوء وغيرها. يمكنك الاطّلاع على هذا الدليل للحصول على مزيد من المعلومات حول التحكّم في إخراج الكاميرا.

يجمع المثال التالي كل شيء من الخطوات السابقة، حالات استخدام CameraX ImageAnalysis وPreview لمالك lifeCycle:

Kotlin

val imageAnalysis = ImageAnalysis.Builder()
    // enable the following line if RGBA output is needed.
    // .setOutputImageFormat(ImageAnalysis.OUTPUT_IMAGE_FORMAT_RGBA_8888)
    .setTargetResolution(Size(1280, 720))
    .setBackpressureStrategy(ImageAnalysis.STRATEGY_KEEP_ONLY_LATEST)
    .build()
imageAnalysis.setAnalyzer(executor, ImageAnalysis.Analyzer { imageProxy ->
    val rotationDegrees = imageProxy.imageInfo.rotationDegrees
    // insert your code here.
    ...
    // after done, release the ImageProxy object
    imageProxy.close()
})

cameraProvider.bindToLifecycle(this as LifecycleOwner, cameraSelector, imageAnalysis, preview)

Java

ImageAnalysis imageAnalysis =
    new ImageAnalysis.Builder()
        // enable the following line if RGBA output is needed.
        //.setOutputImageFormat(ImageAnalysis.OUTPUT_IMAGE_FORMAT_RGBA_8888)
        .setTargetResolution(new Size(1280, 720))
        .setBackpressureStrategy(ImageAnalysis.STRATEGY_KEEP_ONLY_LATEST)
        .build();

imageAnalysis.setAnalyzer(executor, new ImageAnalysis.Analyzer() {
    @Override
    public void analyze(@NonNull ImageProxy imageProxy) {
        int rotationDegrees = imageProxy.getImageInfo().getRotationDegrees();
            // insert your code here.
            ...
            // after done, release the ImageProxy object
            imageProxy.close();
        }
    });

cameraProvider.bindToLifecycle((LifecycleOwner) this, cameraSelector, imageAnalysis, preview);

مصادر إضافية

للحصول على مزيد من المعلومات حول تطبيق CameraX، يمكنك الاطّلاع على المراجع الإضافية التالية.

درس تطبيقي حول الترميز

  • بدء استخدام CameraX
  • نموذج التعليمات البرمجية

  • نماذج تطبيقات CameraX