Мультиспектральная тепловизионная камера (OV5640)

Вариант OV5640 модуля мультиспектральной тепловизионной камеры сочетает 5-мегапиксельный цветной датчик с прогрессивной разверткой (rolling shutter) и тепловизионное ядро FLIR Lepton, поэтому OpenMV Cam может одновременно выполнять конвейеры цветного машинного зрения высокого разрешения и тепловизионной обработки.

Мультиспектральная тепловизионная камера (OV5640)

Полную техническую документацию, фотографии и сведения о заказе см. на странице продукта Multispectral Thermal.

Примечание

Поддерживается только на OpenMV Cam RT1062.

Ключевые особенности

  • OV5640: 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())

Каждая итерация выполняет блокирующий снимок цветного кадра и неблокирующий снимок Lepton — Lepton работает на частоте 9 Гц, поэтому блокировка на нём замедлила бы цветной конвейер. Затем Image.draw_image накладывает оба: color_palette= image.PALETTE_IRONBOW отображает оттенки серого Lepton на тёплую цветовую кривую в стиле FLIR, alpha_palette= смешивает каждый пиксель с использованием квадратичной альфа-карты, а hint= image.BILINEAR сглаживает увеличение.

OV5640 оснащён объективом с автофокусом на основе звуковой катушки (voice-coil). Запустите один проход автофокуса на цветной камере через 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.