حراري متعدد الأطياف (OV5640)

يجمع الإصدار OV5640 من وحدة الكاميرا الحرارية متعددة الأطياف بين مستشعر لون بدقة 5 ميجابكسل من نوع rolling-shutter ونواة حرارية FLIR Lepton، مما يتيح لـ OpenMV Cam تشغيل مسارات الرؤية اللونية عالية الدقة والمسارات الحرارية جنباً إلى جنب.

Multispectral Thermal (OV5640)

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

ملاحظة

مدعوم على OpenMV Cam RT1062 فقط.

أبرز الميزات

  • OV5640: rolling shutter بدقة 5 ميجابكسل للحصول على ألوان أعلى دقة

  • يقبل نوى FLIR Lepton الحرارية بإصدارات 1.x / 2.x / 3.x

  • معالجة حرارية + لونية متزامنة على وحدة واحدة

  • يرى في الظلام الدامس، ويدعم قياس درجة الحرارة

  • تركيز تلقائي وفتحة عدسة F2.0 على مستشعر اللون

الاستخدام

يحصل كل من مستشعر اللون و FLIR Lepton على نسخة csi.CSI خاصة به. يستهدف الاستدعاء الأول المستشعر الأساسي افتراضياً (وهو OV5640)؛ بينما يرتبط الاستدعاء الثاني بـ Lepton عبر تمرير cid= csi.LEPTON. أعد ضبط مستشعر اللون ضبطاً صلباً باستخدام csi.CSI.reset (hard=True) لتشغيل خط التغذية، واضبط Lepton باستخدام hard=False بحيث يعيد مشغّله برمجة الرقاقة فقط دون إعادة تبديل الضبط.

تطابق csi.CSI.framesize ( csi.QVGA ) خرج Lepton مع كاميرا اللون، بحيث تُعيد كل snapshot() إطاراً بدقة 320x240. يقوم مشغّل Lepton داخلياً برفع دقة إطاره الأصلي 80x60 (1.x/2.x) أو 160x120 (3.x) إلى الدقة المطلوبة — فعند QVGA يغطي كل بكسل من Lepton خلية 4x4 أو 2x2 على إطار اللون.

يبقى مخزنان مؤقتان للعمل ثابتين عبر حلقة الإطارات — لوحة ألفا بأبعاد 256x1 مخزّنة كـ image.Image بحيث تصبح بكسلات Lepton الباردة شفافة والبكسلات الساخنة معتمة (يكبح المنحدر التربيعي تفاصيل الخلفية دون سحق المدى المتوسط)، ومخزن إطارات Lepton مخصّص مسبقاً بـ image.Image بحيث يمكن لـ csi.CSI.snapshot (blocking=False, image=...) تعبئته في مكانه في كل تكرار دون إعادة التخصيص:

import time
import csi
import image
import math

alpha_pal = image.Image(256, 1, image.GRAYSCALE)
for i in range(256):
    alpha_pal[i] = int(math.pow((i / 255), 2) * 255)

# Setup the color camera sensor.
csi0 = csi.CSI()
csi0.reset(hard=True)  # force hardware reset.
csi0.pixformat(csi.RGB565)
csi0.framesize(csi.QVGA)

csi1 = csi.CSI(cid=csi.LEPTON)
csi1.reset(hard=False)  # no hardware reset - just configure lepton
csi1.pixformat(csi.GRAYSCALE)
csi1.framesize(csi.QVGA)

# Optional temperature range controls for the LEPTON.
# csi1.ioctl(csi.IOCTL_LEPTON_SET_MODE, True, False)
# csi1.ioctl(csi.IOCTL_LEPTON_SET_RANGE, 20.0, 40.0)

clock = time.clock()

img1 = image.Image(csi1.width(), csi1.height(), csi1.pixformat())

while True:
    clock.tick()
    img0 = csi0.snapshot()
    csi1.snapshot(blocking=False, image=img1)
    img0.draw_image(img1, 0, 0, color_palette=image.PALETTE_IRONBOW,
                    alpha_palette=alpha_pal,
                    hint=image.BILINEAR)
    print(clock.fps())

يأخذ كل تكرار لقطة لونية حاجبة (blocking) ولقطة Lepton غير حاجبة — يعمل Lepton بتردد 9 هرتز، لذا فإن الحجب عليه سيخنق المسار اللوني. ثم تقوم Image.draw_image بدمج الاثنين: color_palette= image.PALETTE_IRONBOW تُسقط تدرج الرمادي لـ Lepton على منحدر لوني دافئ بأسلوب FLIR، و alpha_palette= تمزج كل بكسل باستخدام خريطة ألفا التربيعية، و hint= image.BILINEAR تنعّم رفع الدقة.

يحتوي OV5640 على عدسة تركيز تلقائي مزودة بمشغّل ملف صوتي (voice-coil-actuator). فعّل تمريرة تركيز تلقائي واحدة على كاميرا اللون عبر csi.CSI.ioctl مع csi.IOCTL_TRIGGER_AUTO_FOCUS — يجتاح المستشعر محرك التركيز مرة واحدة ويثبّت على ما هو أمامه:

csi0.ioctl(csi.IOCTL_TRIGGER_AUTO_FOCUS)

أعد إصدار الأمر ioctl في أي وقت يتغير فيه المشهد — فالتركيز التلقائي لقطة واحدة وليس مستمراً.

قياس درجة الحرارة

تقدّم وحدات Lepton الإشعاعية (Lepton 2.5 / 3.5) بيانات درجة حرارة معايرة لكل بكسل. فعّل وضع القياس عبر csi.CSI.ioctl مع csi.IOCTL_LEPTON_SET_MODE، ثم حدّد نافذة درجة الحرارة باستخدام csi.IOCTL_LEPTON_SET_RANGE (min_celsius, max_celsius). يُسقط مشغّل Lepton خطياً قيمة البكسل في تدرج الرمادي 0 على min_celsius والقيمة 255 على max_celsius، بحيث يصبح كل بكسل بحثاً عن درجة حرارة ضمن النافذة المُهيأة. تتشبع البكسلات الأبرد من min_celsius عند 0، وتتشبع البكسلات الأسخن من max_celsius عند 255.

تأخذ csi.IOCTL_LEPTON_SET_MODE علمين (flags). الأول يُشغّل القياس؛ والثاني يختار نطاق درجة حرارة المستشعر:

  • النطاق المنخفض(True, False) — مدى المستشعر من -10 °C إلى +140 °C (مشاهد بحجم الغرفة). حدّد النافذة على منطقة الاهتمام، مثلاً (20.0, 40.0) لتتبع حرارة الجسم:

    csi1.ioctl(csi.IOCTL_LEPTON_SET_MODE, True, False)
    csi1.ioctl(csi.IOCTL_LEPTON_SET_RANGE, 20.0, 40.0)
    
  • النطاق المرتفع(True, True) — مدى المستشعر من -10 °C إلى ~+450 °C نموذجياً (~+400 °C عند درجة حرارة الغرفة) للأجسام الساخنة. حدّد مثلاً (0.0, 400.0) لتتبع الأفران أو العناصر الساخنة:

    csi1.ioctl(csi.IOCTL_LEPTON_SET_MODE, True, True)
    csi1.ioctl(csi.IOCTL_LEPTON_SET_RANGE, 0.0, 400.0)
    

لتحويل بكسل تدرج الرمادي إلى درجة مئوية:

def p_to_temp(p, min_t, max_t):
    return (p * (max_t - min_t)) / 255.0 + min_t

يعمل هذا على البكسلات الفردية أو على الإحصاءات المجمّعة (مثل stats.mean() من Image.get_statistics) داخل منطقة اهتمام (ROI) عند تحديد المناطق الساخنة/الباردة باستخدام Image.find_blobs.