From 1a614202ee9a3495f905be89b9960b1cb7fe8346 Mon Sep 17 00:00:00 2001 From: "Kwabena W. Agyeman" Date: Sun, 20 Jul 2025 21:24:23 -0700 Subject: [PATCH] scripts/examples: Update PureThermal example script to new API. --- .../00-HelloWorld/pure_thermal.py | 97 +++++++++++++------ 1 file changed, 65 insertions(+), 32 deletions(-) diff --git a/scripts/examples/50-OpenMV-Boards/51-Pure-Thermal/00-HelloWorld/pure_thermal.py b/scripts/examples/50-OpenMV-Boards/51-Pure-Thermal/00-HelloWorld/pure_thermal.py index 200f0d21f..cce6b46c8 100644 --- a/scripts/examples/50-OpenMV-Boards/51-Pure-Thermal/00-HelloWorld/pure_thermal.py +++ b/scripts/examples/50-OpenMV-Boards/51-Pure-Thermal/00-HelloWorld/pure_thermal.py @@ -4,14 +4,14 @@ # # Pure Thermal Example Script # -# Thanks for buying the Pure Thermal OpenMV! This example script shows off thermal video -# overlay onto the color camera image and driving the attached LCD screen and HDMI output. +# Thanks for buying the Pure Thermal OpenMV! This example script shows +# off thermal video overlay onto the color camera image and driving +# the attached LCD screen and HDMI output. -import sensor +import csi import image import time import display -import fir import math import tfp410 @@ -19,13 +19,42 @@ import tfp410 # Color Tracking Thresholds (Grayscale Min, Grayscale Max) threshold_list = [(200, 255)] -sensor.reset() -sensor.set_pixformat(sensor.RGB565) -sensor.set_framesize(sensor.WVGA) +# Set the target temp range here +min_temp_in_celsius = 20.0 +max_temp_in_celsius = 40.0 + +csi0 = csi.CSI(cid=csi.OV5640) +csi0.reset() +csi0.pixformat(csi.RGB565) +csi0.framesize(csi.WVGA) time.sleep_ms(50) -fir.init(fir.FIR_LEPTON) -fir_img = image.Image(fir.width(), fir.height(), sensor.GRAYSCALE) +csi1 = csi.CSI(cid=csi.LEPTON) +csi1.reset(hard=False) +csi1.pixformat(csi.GRAYSCALE) +csi1.framesize(csi.QQVGA) + +# Enables exact temperature measurments from the flir lepton. +# The second argument turns high gain mode on for high temp reading. +csi1.ioctl(csi.IOCTL_LEPTON_SET_MODE, True, False) +csi1.ioctl( + csi.IOCTL_LEPTON_SET_RANGE, min_temp_in_celsius, max_temp_in_celsius +) + +print( + "Lepton Res (%dx%d)" + % ( + csi1.ioctl(csi.IOCTL_LEPTON_GET_WIDTH), + csi1.ioctl(csi.IOCTL_LEPTON_GET_HEIGHT), + ) +) + +print( + "Radiometry Available: " + + ("Yes" if csi1.ioctl(csi.IOCTL_LEPTON_GET_RADIOMETRY) else "No") +) + +fir_img = image.Image(csi1.width(), csi1.height(), image.GRAYSCALE) time.sleep_ms(50) lcd = display.RGBDisplay(framesize=display.FWVGA, refresh=60) @@ -33,7 +62,7 @@ lcd.backlight(True) hdmi = tfp410.TFP410() time.sleep_ms(50) -alpha_pal = image.Image(256, 1, sensor.GRAYSCALE) +alpha_pal = image.Image(256, 1, image.GRAYSCALE) for i in range(256): alpha_pal[i] = int(math.pow((i / 255), 2) * 255) @@ -42,18 +71,20 @@ to_max = None def map_g_to_temp(g): - return ((g * (to_max - to_min)) / 255.0) + to_min + return ( + (g * (max_temp_in_celsius - min_temp_in_celsius)) / 255.0 + ) + min_temp_in_celsius +# Kickstart thermal camera capture. +csi1.snapshot(update=False, blocking=True, image=fir_img) + while True: - img = sensor.snapshot() - # ta: Ambient temperature - # ir: Object temperatures (IR array) - # to_min: Minimum object temperature - # to_max: Maximum object temperature - ta, ir, to_min, to_max = fir.read_ir() + img = csi0.snapshot() + + # Capture the thermal image without blocking. + csi1.snapshot(update=False, blocking=False, image=fir_img) - fir.draw_ir(fir_img, ir, color_palette=None) fir_img_size = fir_img.width() * fir_img.height() # Find IR Blobs @@ -65,8 +96,12 @@ while True: # Collect stats into a list of tuples blob_stats = [] for b in blobs: - blob_stats.append((b.rect(), map_g_to_temp(img.get_statistics(thresholds=threshold_list, - roi=b.rect()).mean()))) + blob_stats.append( + (b.rect(), map_g_to_temp(fir_img.get_statistics( + thresholds=threshold_list, roi=b.rect() + ).mean())) + ) + x_scale = img.width() / fir_img.width() y_scale = img.height() / fir_img.height() img.draw_image(fir_img, 0, 0, x_scale=x_scale, y_scale=y_scale, @@ -76,19 +111,17 @@ while True: # Draw stuff on the colored image for b in blobs: - img.draw_rectangle(int(b.rect()[0] * x_scale), int(b.rect()[1] * y_scale), - int(b.rect()[2] * x_scale), int(b.rect()[3] * y_scale)) + img.draw_rectangle(int(b.rect()[0] * x_scale), + int(b.rect()[1] * y_scale), + int(b.rect()[2] * x_scale), + int(b.rect()[3] * y_scale)) img.draw_cross(int(b.cx() * x_scale), int(b.cy() * y_scale)) + for blob_stat in blob_stats: - img.draw_string(int((blob_stat[0][0] * x_scale) + 4), int((blob_stat[0][1] * y_scale) + 1), + img.draw_string(int((blob_stat[0][0] * x_scale) + 4), + int((blob_stat[0][1] * y_scale) + 1), '%.2f C' % blob_stat[1], mono_space=False, scale=2) - # Draw ambient, min and max temperatures. - img.draw_string(4, 0, 'Lepton Temp: %0.2f C' % ta, - color=(255, 255, 255), mono_space=False, scale=2) - img.draw_string(4, 18, 'Min Temp: %0.2f C' % to_min, - color=(255, 255, 255), mono_space=False, scale=2) - img.draw_string(4, 36, 'Max Temp: %0.2f C' % to_max, - color=(255, 255, 255), mono_space=False, scale=2) - - lcd.write(img, hint=(image.BILINEAR | image.CENTER | image.SCALE_ASPECT_KEEP)) + lcd.write(img, hint=( + image.BILINEAR | image.CENTER | image.SCALE_ASPECT_KEEP + ))