מולטי-ספקטרלי תרמי (OV5640)

גרסת ה-OV5640 של מודול המצלמה התרמית המולטי-ספקטרלית משלבת חיישן צבע 5MP מסוג rolling-shutter עם ליבה תרמית FLIR Lepton, כך שה-OpenMV Cam יכול להריץ בו-זמנית צינורות עיבוד של ראייה צבעונית ברזולוציה גבוהה ושל הדמיה תרמית.

Multispectral Thermal (OV5640)

ל-datasheet המלא, תמונות והזמנה ראו את עמוד המוצר Multispectral Thermal.

הערה

נתמך ב-OpenMV Cam RT1062 בלבד.

עיקרי הדברים

  • OV5640: חיישן 5MP מסוג rolling shutter לצבע ברזולוציה גבוהה יותר

  • מקבל ליבות תרמיות FLIR Lepton 1.x / 2.x / 3.x

  • עיבוד תרמי + צבע בו-זמנית על מודול אחד

  • רואה בחושך מוחלט, תומך במדידת טמפרטורה

  • מיקוד אוטומטי וצמצם F2.0 בחיישן הצבע

שימוש

חיישן הצבע וה-FLIR Lepton מקבלים כל אחד מופע csi.CSI משלו. הקריאה הראשונה ברירת המחדל היא לחיישן הראשי (ה-OV5640); השנייה נקשרת ל-Lepton באמצעות העברת cid= csi.LEPTON. בצעו אתחול חומרה מלא (hard-reset) לחיישן הצבע עם csi.CSI.reset (hard=True) כדי להעלות את מתח ההזנה, והגדירו את ה-Lepton עם hard=False כך שהדרייבר שלו רק יתכנת מחדש את השבב מבלי לבצע איפוס מחדש.

csi.CSI.framesize ( csi.QVGA ) מתאים את פלט ה-Lepton למצלמת הצבע, כך שכל snapshot() מחזיר פריים בגודל 320x240. הדרייבר של ה-Lepton מבצע פנימית הגדלה (upscale) של הפריים המקורי שלו בגודל 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())

כל איטרציה לוקחת תמונת בזק (snapshot) צבעונית חוסמת ותמונת בזק (snapshot) של Lepton לא-חוסמת — ה-Lepton פועל ב-9 Hz ולכן חסימה עליו תחנוק את צינור הצבע. 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 מקבל שני דגלים. הראשון מפעיל את המדידה; השני בוחר את טווח הטמפרטורה של החיישן:

  • טווח נמוך(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.