4.18. المستشعرات المتعددة¶
تقرن حفنة من كاميرات OpenMV Cam مستشعرَي صورة على اللوحة نفسها -- وأكثرها شيوعاً كاميرا ملونة إلى جانب مستشعر حراري FLIR® Lepton®، لكن الشكل نفسه ينطبق على لوحات الألوان المقترنة بالأحداث وأي عتاد ثنائي المستشعر مستقبلي. لكل مستشعر مصفوفة بكسل خاصة به، وناقل تحكم خاص به، ويشغّل خط معالجته الخاص بمعدل إطاراته الخاص. تتوسع واجهة CSI لتغطيتها بأن تتيح للتطبيق إنشاء كائن CSI واحد لكل مستشعر فيزيائي.
4.18.1. تحديد المستشعر¶
يأخذ مُنشئ CSI وسيطاً cid يسمّي مستشعراً محدداً على اللوحة. تختار cid=-1 (القيمة الافتراضية) المستشعر الأساسي؛ بينما تختار ثوابت cid المسماة مستشعراً ثانوياً حسب معرّف الشريحة:
import csi
csi_rgb = csi.CSI() # primary colour sensor
csi_thermal = csi.CSI(cid=csi.LEPTON) # FLIR® Lepton®
تمتلك كل نسخة تكوينها الخاص -- تنسيق البكسل وحجم الإطار وأزرار التعريض/الكسب وتجمع مخزن الإطارات -- وتُعاد ضبطها وتُكوَّن وتُقرأ بشكل مستقل عن الأخرى. ثوابت المستشعرات الثانوية المدعومة (LEPTON وGENX320 وغيرها مما هو مدرج في مرجع CSI) تسمّي الشريحة التي يتوقعها التطبيق على المنفذ الثانوي؛ ويُفشل المشغّل عملية الإنشاء إذا لم تتطابق الشريحة الفعلية.
4.18.2. الالتقاط من كلا المستشعرين¶
يشغّل كل مستشعر خط التقاطه بشكل مستقل عن الآخر -- فقد يسلّم المستشعر الملون ثلاثين إطاراً في الثانية بينما يسلّم Lepton® تسعة. الطريقة المباشرة للتعامل مع هذا التفاوت هي أن ندع المستشعر الأسرع يقود الحلقة وأن نقرأ المستشعر الأبطأ بشكل غير حاجب، فنأخذ ما هو جاهز ونتخطى التكرار عندما لا يكون هناك شيء:
import csi
csi_rgb = csi.CSI()
csi_thermal = csi.CSI(cid=csi.LEPTON)
csi_rgb.reset() # powers the rail, pulses RESET
csi_rgb.pixformat(csi.RGB565)
csi_rgb.framesize(csi.QVGA)
csi_thermal.reset(hard=False) # I2C reconfigure only
csi_thermal.pixformat(csi.GRAYSCALE)
csi_thermal.framesize(csi.QQVGA)
while True:
rgb_img = csi_rgb.snapshot() # blocks for next colour frame
thermal_img = csi_thermal.snapshot(blocking=False) # returns None if not ready
if thermal_img is not None:
# process aligned colour + thermal pair
pass
else:
# process colour only on this iteration
pass
تنظّم snapshot() الحاجبة وتيرة الحلقة؛ بينما تعيد النسخة غير الحاجبة أحدث إطار حراري عندما يكون قد وصل إطار جديد منذ الاستدعاء السابق، وتعيد None بخلاف ذلك. يستمر التطبيق في العمل بمعدل إطارات المستشعر الملون ويحصل على إطار حراري كلما أنتج Lepton® واحداً.
النمط المعاكس -- لقطتان حاجبتان متتاليتان -- يعمل أيضاً، لكن الحلقة عندئذ تعمل بمعدل المستشعر الأبطأ من الاثنين، مع توقف خط معالجة المستشعر الأسرع بين التكرارات. اختر أي معدل تريد معالجة التطبيق اللاحقة قيادته فعلياً.
4.18.4. تحديد مصدر البث¶
تملك الكاميرات ذات المستشعرين نسختين من CSI لكن مع ذلك مخزن إطارات بث واحد فقط بينهما. يختار وسيط في المُنشئ أي مستشعر تغذّي إطاراته المعاينة:
csi_rgb = csi.CSI() # primary
csi_thermal = csi.CSI(cid=csi.LEPTON,
stream=True) # preview source
تجعل stream=True النسخة المسماة هي المصدر. وبدون وسيط stream= يكون المستشعر الأساسي (cid=-1، القيمة الافتراضية) هو المصدر؛ أما النسخ المبنية بـ cid= لمستشعر ثانوي فتبقى صامتة في المعاينة ما لم تُمرَّر stream=True صراحةً. ولا تزال استدعاءات snapshot() على المستشعر غير المحدد تلتقط الإطارات إلى مخازن إطارات ذلك المستشعر بشكل طبيعي -- إنها فقط لا تحدّث المعاينة.