Multispectral Thermal (PAG7936)

PAG7936 เป็นตัวเลือกของโมดูลกล้อง Multispectral Thermal ที่จับคู่เซนเซอร์สีแบบ global-shutter ขนาด 1MP กับแกน FLIR Lepton ความร้อน ทำให้ OpenMV Cam สามารถรันไปป์ไลน์การมองเห็นสีและความร้อนควบคู่กันได้

Multispectral Thermal (PAG7936)

สำหรับข้อมูลจำเพาะเต็มรูปแบบ รูปภาพ และการสั่งซื้อ ดูได้ที่ หน้าสินค้า Multispectral Thermal

Note

รองรับเฉพาะ OpenMV N6 เท่านั้น

ไฮไลต์

  • PAG7936: global shutter 1MP

  • รองรับแกน FLIR Lepton 1.x / 2.x / 3.x

  • ประมวลผลความร้อน + สีพร้อมกันบนโมดูลเดียว

  • มองเห็นได้ในความมืดสนิท รองรับการวัดอุณหภูมิ

  • Global shutter รองรับการเคลื่อนไหวเร็วโดยไม่มีปัญหาจาก rolling-shutter

การใช้งาน

เซนเซอร์สีและ FLIR Lepton แต่ละตัวจะได้รับอินสแตนซ์ csi.CSI ของตัวเอง การเรียกครั้งแรกจะใช้เซนเซอร์หลัก (PAG7936) เป็นค่าเริ่มต้น การเรียกครั้งที่สองจะผูกกับ Lepton โดยส่ง cid= csi.LEPTON รีเซ็ตเซนเซอร์สีแบบ hard reset ด้วย csi.CSI.reset (hard=True) เพื่อเปิดใช้ rail และกำหนดค่า Lepton ด้วย hard=False เพื่อให้ไดรเวอร์เพียงโปรแกรมชิปใหม่โดยไม่สลับ reset

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 ที่เย็นกลายเป็นโปร่งใสและพิกเซลที่ร้อนกลายเป็นทึบแสง (การลาด quadratic ลดรายละเอียดพื้นหลังโดยไม่บีบช่วงกลาง) และบัฟเฟอร์เฟรม 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 แบบ non-blocking — Lepton ทำงานที่ 9 Hz ดังนั้นการ blocking จะจำกัดไปป์ไลน์สี Image.draw_image จะรวมทั้งสองเข้าด้วยกัน: color_palette= image.PALETTE_IRONBOW แมประดับสีเทาของ Lepton เป็นช่วงสีอุ่นสไตล์ FLIR, alpha_palette= ผสมแต่ละพิกเซลโดยใช้แผนที่อัลฟา quadratic และ hint= image.BILINEAR ทำให้การอัปสเกลเนียนขึ้น

การวัดอุณหภูมิ

Lepton แบบ Radiometric (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 รับสองแฟล็ก แฟล็กแรกเปิดการวัด แฟล็กที่สองเลือกช่วงอุณหภูมิของเซนเซอร์:

  • ช่วงต่ำ(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= — เมทริกซ์โฮโมกราฟี 3x3 เป็น ulab.numpy array 2 มิติ บน OpenMV N6 GPU จะประมวลผลการฉายแต่ละพิกเซลระหว่างการวาดเดียวกัน ดังนั้นเฟรม Lepton สามารถจัดตำแหน่งใหม่เทียบกับมุมมองของกล้องสีได้โดยไม่ต้องผ่านการ warp แยกต่างหาก สอบเทียบเมทริกซ์ต่อกล้องด้วย เครื่องมือ thermal-overlay-calibration

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 ที่เล็กกว่าลงในเฟรมสีที่ใหญ่กว่าเป็นส่วนหนึ่งของการวาด ดังนั้นปัจจัยการอัปสเกลจึงถูกฝังอยู่ในเมทริกซ์เองแทนที่จะนำไปใช้แยกต่างหาก