توفّر حالة استخدام تحليل الصور لتطبيقك صورة يمكن لوحدة المعالجة المركزية الوصول إليها، ويمكنك إجراء معالجة الصور أو الرؤية الحاسوبية أو استنتاج تعلُّم الآلة عليها. ينفّذ التطبيق طريقة 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.setImageQueueDepth().
باستخدام محلّل ذي وقت استجابة منخفض وأداء عالٍ، حيث يكون إجمالي الوقت المستغرَق لتحليل صورة أقل من مدة إطار CameraX (على سبيل المثال، 16 ملي ثانية لـ 60 لقطة في الثانية)، يوفّر أي من وضعَي التشغيل تجربة سلسة بشكل عام. قد يظل وضع الحظر مفيدًا في بعض السيناريوهات، مثل عند التعامل مع حالات عدم استقرار النظام القصيرة جدًا.
في حال استخدام محلّل عالي الأداء ويستغرق وقتًا طويلاً للاستجابة، يجب استخدام وضع الحظر مع قائمة انتظار أطول للتعويض عن وقت الاستجابة. ومع ذلك، يُرجى العِلم أنّ التطبيق لا يزال بإمكانه معالجة جميع اللقطات.
في حال استخدام محلّل يستغرق وقتًا طويلاً في المعالجة (لا يمكنه معالجة جميع اللقطات)، قد يكون وضع عدم الحظر خيارًا أكثر ملاءمةً، لأنّه يجب تجاهل اللقطات في مسار التحليل، ولكن يمكن لحالات الاستخدام الأخرى المرتبطة والمتزامنة رؤية جميع اللقطات.
التنفيذ
لاستخدام ميزة تحليل الصور في تطبيقك، اتّبِع الخطوات التالية:
- إنشاء حالة استخدام
ImageAnalysis - أنشئ
ImageAnalysis.Analyzer. - اضبط المحلّل على
ImageAnalysis. - اربط مالك مراحل النشاط ومحدد الكاميرا وحالة الاستخدام
ImageAnalysisبمراحل النشاط.
بعد الربط مباشرةً، ترسل CameraX الصور إلى المحلّل المسجَّل.
بعد إكمال التحليل، يمكنك استدعاء
ImageAnalysis.clearAnalyzer()
أو إلغاء ربط حالة استخدام ImageAnalysis لإيقاف التحليل.
إنشاء حالة استخدام ImageAnalysis
يربط ImageAnalysis
المحلّل (مستهلك الصور) بـ CameraX، وهو منتج صور.
يمكن للتطبيقات استخدام
ImageAnalysis.Builder
لإنشاء كائن ImageAnalysis. باستخدام ImageAnalysis.Builder،
يمكن للتطبيق ضبط ما يلي:
- مَعلمات الصور الناتجة:
- التنسيق: تتيح واجهة CameraX استخدام
YUV_420_888وRGBA_8888من خلالsetOutputImageFormat(int). التنسيق التلقائي هوYUV_420_888. - Resolution وAspectRatio: يمكنك ضبط أيّ من هاتين المَعلمتين، ولكن لا يمكنك ضبط كلتا القيمتين في الوقت نفسه.
- الدوران:
- Target Name: استخدِم هذه المَعلمة لأغراض تصحيح الأخطاء.
- التنسيق: تتيح واجهة CameraX استخدام
- عناصر التحكّم في تدفق الصور:
يمكن للتطبيقات ضبط درجة الدقة أو نسبة العرض إلى الارتفاع، ولكن ليس
كليهما. تعتمد دقة الإخراج الدقيقة على الحجم المطلوب للتطبيق (أو نسبة العرض إلى الارتفاع) وإمكانات الأجهزة، وقد تختلف عن الحجم أو النسبة المطلوبة. للحصول على معلومات حول خوارزمية مطابقة الدقة، يُرجى الاطّلاع على مستندات 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 للتعرّف على إعدادات الفضاء اللوني ومكان استرداد وحدات بايت البكسل.
داخل المحلّل، يجب أن ينفّذ التطبيق ما يلي:
- تحليل لقطة معيّنة بأسرع وقت ممكن، ويُفضَّل أن يكون ذلك ضمن الحدّ الزمني المحدّد لعدد اللقطات في الثانية (على سبيل المثال، أقل من 32 ملي ثانية في حالة 30 لقطة في الثانية). إذا لم يتمكّن التطبيق من تحليل اللقطة بسرعة كافية، يمكنك استخدام إحدى آليات إسقاط اللقطات المتوافقة.
- يمكنك تحرير
ImageProxyإلى CameraX من خلال استدعاءImageProxy.close(). يُرجى العِلم أنّه يجب عدم استدعاء دالة الإغلاق (Media.Image.close()) الخاصة بـ Media.Image المغلَّفة.
يمكن للتطبيقات استخدام Media.Image المغلَّف داخل ImageProxy مباشرةً.
يجب عدم استدعاء Media.Image.close() على الصورة المغلَّفة لأنّ ذلك سيؤدي إلى تعطُّل
آلية مشاركة الصور داخل CameraX، بل يجب استخدام
ImageProxy.close()
لإصدار Media.Image الأساسي إلى CameraX.
ضبط المحلّل لـ ImageAnalysis
بعد إنشاء محلّل، استخدِم
ImageAnalysis.setAnalyzer()
لتسجيله وبدء التحليل. بعد الانتهاء من التحليل، استخدِم
ImageAnalysis.clearAnalyzer()
لإزالة المحلّل المسجَّل.
يمكن ضبط محلّل نشط واحد فقط لتحليل الصور. يؤدي استدعاء
ImageAnalysis.setAnalyzer() إلى استبدال المحلّل المسجَّل إذا كان موجودًا
بالفعل. يمكن للتطبيقات ضبط محلّل جديد في أي وقت، قبل ربط حالة الاستخدام أو بعده.
ربط ImageAnalysis بدورة حياة
ننصح بشدة بربط ImageAnalysis بدورة حياة AndroidX حالية باستخدام الدالة ProcessCameraProvider.bindToLifecycle(). يُرجى العِلم أنّ الدالة bindToLifecycle() تعرض جهاز Camera المحدّد، والذي يمكن استخدامه لضبط الإعدادات المتقدّمة بدقة، مثل درجة الإضاءة وغيرها. يُرجى الاطّلاع على هذا الدليل لمزيد من المعلومات حول التحكّم في مخرجات الكاميرا.
يجمع المثال التالي كل ما ورد في الخطوات السابقة، ويربط حالات استخدام ImageAnalysis وPreview في CameraX بمالك lifeCycle:
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)
مراجع إضافية
لمزيد من المعلومات حول CameraX، يمكنك الاطّلاع على المراجع الإضافية التالية.
درس تطبيقي حول الترميز
عيّنة تعليمات برمجية