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

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

Multispectral Thermal (PAG7936)

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

ملاحظة

مدعوم على OpenMV N6 فقط.

أبرز الميزات

  • PAG7936: global shutter بدقة 1 ميجابكسل

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

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

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

  • يتعامل global shutter مع الحركة السريعة دون تشوهات rolling-shutter

الاستخدام

يحصل كل من مستشعر اللون و FLIR Lepton على نسخة csi.CSI خاصة به. يستهدف الاستدعاء الأول المستشعر الأساسي افتراضياً (وهو PAG7936)؛ بينما يرتبط الاستدعاء الثاني بـ 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 تنعّم رفع الدقة.

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

تقدّم وحدات 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.

محاذاة معجّلة بوحدة معالجة الرسوميات (GPU)

تقبل Image.draw_image وسيطاً transform= — وهو مصفوفة تحويل تماثلي (homography) بأبعاد 3x3 على هيئة مصفوفة ulab.numpy ثنائية الأبعاد. على OpenMV N6 تشغّل وحدة GPU الإسقاط لكل بكسل أثناء عملية الرسم نفسها، بحيث يمكن إعادة محاذاة إطار Lepton مع منظور كاميرا اللون دون تمريرة تشويه (warp) منفصلة. عاير المصفوفة لكل كاميرا باستخدام أداة معايرة الطبقة الحرارية الفوقية

import time
import csi
import image
from ulab import numpy as np
import math

# Calibration matrix from the thermal-overlay-calibration tool.
m = np.array([
    [3.704807, 0.257018, 37.260564],
    [0.052147, 3.609977, -7.831831],
    [0.000294, 0.000552, 1.000000],
])

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.VGA)

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

# 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,
                    transform=m)
    print(clock.fps())

لاحظ أن هذا الإصدار يشغّل كاميرا اللون عند csi.VGA (640x480) و Lepton عند csi.QQVGA (160x120) — يُسقط التحويل التماثلي إطار Lepton الأصغر داخل إطار اللون الأكبر كجزء من عملية الرسم، بحيث يُدمج عامل رفع الدقة في المصفوفة نفسها بدلاً من تطبيقه على حدة.