diff --git a/scripts/examples/50-OpenMV-Boards/51-Pure-Thermal/00-HelloWorld/blinky.py b/scripts/examples/50-OpenMV-Boards/51-Pure-Thermal/00-HelloWorld/blinky.py new file mode 100644 index 000000000..b01dcd3f3 --- /dev/null +++ b/scripts/examples/50-OpenMV-Boards/51-Pure-Thermal/00-HelloWorld/blinky.py @@ -0,0 +1,16 @@ +# This work is licensed under the MIT license. +# Copyright (c) 2013-2024 OpenMV LLC. All rights reserved. +# https://github.com/openmv/openmv/blob/master/LICENSE +# +# Blinky example + +import time +from machine import LED + +led = LED("LED_BLUE") + +while True: + led.on() + time.sleep_ms(500) + led.off() + time.sleep_ms(500) diff --git a/scripts/examples/50-OpenMV-Boards/51-Pure-Thermal/00-HelloWorld/helloworld.py b/scripts/examples/50-OpenMV-Boards/51-Pure-Thermal/00-HelloWorld/helloworld.py new file mode 100644 index 000000000..cf3594b92 --- /dev/null +++ b/scripts/examples/50-OpenMV-Boards/51-Pure-Thermal/00-HelloWorld/helloworld.py @@ -0,0 +1,22 @@ +# This work is licensed under the MIT license. +# Copyright (c) 2013-2024 OpenMV LLC. All rights reserved. +# https://github.com/openmv/openmv/blob/master/LICENSE +# +# Hello World Example +# +# Welcome to the OpenMV IDE! Click on the green run arrow button below to run the script! + +import sensor +import time + +sensor.reset() # Reset and initialize the sensor. +sensor.set_pixformat(sensor.RGB565) # Set pixel format to RGB565 (or GRAYSCALE) +sensor.set_framesize(sensor.QVGA) # Set frame size to QVGA (320x240) +sensor.skip_frames(time=2000) # Wait for settings take effect. +clock = time.clock() # Create a clock object to track the FPS. + +while True: + clock.tick() # Update the FPS clock. + img = sensor.snapshot() # Take a picture and return the image. + print(clock.fps()) # Note: OpenMV Cam runs about half as fast when connected + # to the IDE. The FPS should increase once disconnected. 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 new file mode 100644 index 000000000..200f0d21f --- /dev/null +++ b/scripts/examples/50-OpenMV-Boards/51-Pure-Thermal/00-HelloWorld/pure_thermal.py @@ -0,0 +1,94 @@ +# This work is licensed under the MIT license. +# Copyright (c) 2013-2024 OpenMV LLC. All rights reserved. +# https://github.com/openmv/openmv/blob/master/LICENSE +# +# 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. + +import sensor +import image +import time +import display +import fir +import math +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) +time.sleep_ms(50) + +fir.init(fir.FIR_LEPTON) +fir_img = image.Image(fir.width(), fir.height(), sensor.GRAYSCALE) +time.sleep_ms(50) + +lcd = display.RGBDisplay(framesize=display.FWVGA, refresh=60) +lcd.backlight(True) +hdmi = tfp410.TFP410() +time.sleep_ms(50) + +alpha_pal = image.Image(256, 1, sensor.GRAYSCALE) +for i in range(256): + alpha_pal[i] = int(math.pow((i / 255), 2) * 255) + +to_min = None +to_max = None + + +def map_g_to_temp(g): + return ((g * (to_max - to_min)) / 255.0) + to_min + + +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() + + fir.draw_ir(fir_img, ir, color_palette=None) + fir_img_size = fir_img.width() * fir_img.height() + + # Find IR Blobs + blobs = fir_img.find_blobs(threshold_list, + pixels_threshold=(fir_img_size // 100), + area_threshold=(fir_img_size // 100), + merge=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()))) + 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, + color_palette=image.PALETTE_IRONBOW, + alpha_palette=alpha_pal, + hint=image.BICUBIC) + + # 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_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), + '%.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)) diff --git a/scripts/examples/index.csv b/scripts/examples/index.csv index f80dc139f..451d5d6c0 100644 --- a/scripts/examples/index.csv +++ b/scripts/examples/index.csv @@ -1,6 +1,6 @@ # "Relative Path Regex", "Board Type Regex", "Sensor Type Regex", "Flatten Regex" -"examples/00-HelloWorld/blinky.py", ".+", ".+", "" -"examples/00-HelloWorld/helloworld.py", ".+", "^(?!None).*$", "" +"examples/00-HelloWorld/blinky.py", "^(?!OPENMVPT).*$", ".+", "" +"examples/00-HelloWorld/helloworld.py", "^(?!OPENMVPT).*$", "^(?!None).*$", "" "examples/01-Camera/00-Snapshot", ".+", "^(?!None).*$", "" "examples/01-Camera/01-Video-Recording", ".+", "^(?!None).*$", "" "examples/01-Camera/02-Optical-Flow", ".+", "^(?!None).*$", "" diff --git a/src/omv/boards/OPENMVPT/main_py.h b/src/omv/boards/OPENMVPT/main_py.h index 33f0b9730..e449655bf 100644 --- a/src/omv/boards/OPENMVPT/main_py.h +++ b/src/omv/boards/OPENMVPT/main_py.h @@ -1,91 +1,97 @@ static const char fresh_main_py[] = - "import sensor, image, time, display, fir, math, pyb\n" + "# This work is licensed under the MIT license.\n" + "# Copyright (c) 2013-2024 OpenMV LLC. All rights reserved.\n" + "# https://github.com/openmv/openmv/blob/master/LICENSE\n" + "#\n" + "# Pure Thermal Example Script\n" + "#\n" + "# Thanks for buying the Pure Thermal OpenMV! This example script shows off thermal video\n" + "# overlay onto the color camera image and driving the attached LCD screen and HDMI output.\n" + "\n" + "import sensor\n" + "import image\n" + "import time\n" + "import display\n" + "import fir\n" + "import math\n" + "import tfp410\n" "\n" - "from machine import I2C\n" - "from vl53l1x import VL53L1X\n" "\n" "# Color Tracking Thresholds (Grayscale Min, Grayscale Max)\n" "threshold_list = [(200, 255)]\n" "\n" - "def main():\n" + "sensor.reset()\n" + "sensor.set_pixformat(sensor.RGB565)\n" + "sensor.set_framesize(sensor.WVGA)\n" + "time.sleep_ms(50)\n" "\n" - " i2c = I2C(2)\n" - " # distance = VL53L1X(i2c)\n" + "fir.init(fir.FIR_LEPTON)\n" + "fir_img = image.Image(fir.width(), fir.height(), sensor.GRAYSCALE)\n" + "time.sleep_ms(50)\n" "\n" - " sensor.reset()\n" - " sensor.set_pixformat(sensor.RGB565)\n" - " sensor.set_framesize(sensor.VGA)\n" - " time.sleep_ms(50)\n" + "lcd = display.RGBDisplay(framesize=display.FWVGA, refresh=60)\n" + "lcd.backlight(True)\n" + "hdmi = tfp410.TFP410()\n" + "time.sleep_ms(50)\n" "\n" - " fir.init(fir.FIR_LEPTON)\n" - " fir_img = sensor.alloc_extra_fb(fir.width(), fir.height(), sensor.GRAYSCALE)\n" - " time.sleep_ms(50)\n" + "alpha_pal = image.Image(256, 1, sensor.GRAYSCALE)\n" + "for i in range(256):\n" + " alpha_pal[i] = int(math.pow((i / 255), 2) * 255)\n" "\n" - " lcd = display.RGBDisplay(framesize=display.FWVGA, refresh=60)\n" + "to_min = None\n" + "to_max = None\n" "\n" - " alpha_pal = image.Image(256, 1, sensor.GRAYSCALE)\n" - " for i in range(256): alpha_pal[i] = int(math.pow((i / 255), 2) * 255)\n" "\n" - " to_min = None\n" - " to_max = None\n" + "def map_g_to_temp(g):\n" + " return ((g * (to_max - to_min)) / 255.0) + to_min\n" "\n" - " def map_g_to_temp(g):\n" - " return ((g * (to_max - to_min)) / 255.0) + to_min\n" "\n" - " while True:\n" - " img = sensor.snapshot()\n" - " # ta: Ambient temperature\n" - " # ir: Object temperatures (IR array)\n" - " # to_min: Minimum object temperature\n" - " # to_max: Maximum object temperature\n" - " ta, ir, to_min, to_max = fir.read_ir()\n" + "while True:\n" + " img = sensor.snapshot()\n" + " # ta: Ambient temperature\n" + " # ir: Object temperatures (IR array)\n" + " # to_min: Minimum object temperature\n" + " # to_max: Maximum object temperature\n" + " ta, ir, to_min, to_max = fir.read_ir()\n" "\n" - " fir.draw_ir(fir_img, ir, color_palette = None)\n" - " fir_img_size = fir_img.width() * fir_img.height()\n" + " fir.draw_ir(fir_img, ir, color_palette=None)\n" + " fir_img_size = fir_img.width() * fir_img.height()\n" "\n" - " # Find IR Blobs\n" - " blobs = fir_img.find_blobs(threshold_list,\n" - " pixels_threshold = (fir_img_size // 100),\n" - " area_threshold = (fir_img_size // 100),\n" - " merge = True)\n" + " # Find IR Blobs\n" + " blobs = fir_img.find_blobs(threshold_list,\n" + " pixels_threshold=(fir_img_size // 100),\n" + " area_threshold=(fir_img_size // 100),\n" + " merge=True)\n" "\n" - " # Collect stats into a list of tuples\n" - " blob_stats = []\n" - " for b in blobs:\n" - " blob_stats.append((b.rect(), map_g_to_temp(fir_img.get_statistics(thresholds = threshold_list,\n" - " roi = b.rect()).mean())))\n" - " x_scale = img.width() / fir_img.width()\n" - " y_scale = img.height() / fir_img.height()\n" - " img.draw_image(fir_img, 0, 0, x_scale = x_scale, y_scale = y_scale,\n" - " color_palette = image.PALETTE_IRONBOW,\n" - " alpha_palette = alpha_pal,\n" - " hint = image.BICUBIC)\n" + " # Collect stats into a list of tuples\n" + " blob_stats = []\n" + " for b in blobs:\n" + " blob_stats.append((b.rect(), map_g_to_temp(img.get_statistics(thresholds=threshold_list,\n" + " roi=b.rect()).mean())))\n" + " x_scale = img.width() / fir_img.width()\n" + " y_scale = img.height() / fir_img.height()\n" + " img.draw_image(fir_img, 0, 0, x_scale=x_scale, y_scale=y_scale,\n" + " color_palette=image.PALETTE_IRONBOW,\n" + " alpha_palette=alpha_pal,\n" + " hint=image.BICUBIC)\n" "\n" - " # Draw stuff on the colored image\n" - " for b in blobs:\n" - " img.draw_rectangle(int(b.rect()[0] * x_scale), int(b.rect()[1] * y_scale),\n" - " int(b.rect()[2] * x_scale), int(b.rect()[3] * y_scale))\n" - " img.draw_cross(int(b.cx() * x_scale), int(b.cy() * y_scale))\n" - " for blob_stat in blob_stats:\n" - " img.draw_string(int((blob_stat[0][0] * x_scale) + 4), int((blob_stat[0][1] * y_scale) + 1),\n" - " '%.2f C' % blob_stat[1], mono_space = False, scale = 2)\n" + " # Draw stuff on the colored image\n" + " for b in blobs:\n" + " img.draw_rectangle(int(b.rect()[0] * x_scale), int(b.rect()[1] * y_scale),\n" + " int(b.rect()[2] * x_scale), int(b.rect()[3] * y_scale))\n" + " img.draw_cross(int(b.cx() * x_scale), int(b.cy() * y_scale))\n" + " for blob_stat in blob_stats:\n" + " img.draw_string(int((blob_stat[0][0] * x_scale) + 4), int((blob_stat[0][1] * y_scale) + 1),\n" + " '%.2f C' % blob_stat[1], mono_space=False, scale=2)\n" "\n" - " # Draw ambient, min and max temperatures.\n" - " img.draw_string(4, 0, 'Lepton Temp: %0.2f C' % ta, color = (255, 255, 255), mono_space = False, scale = 2)\n" - " img.draw_string(4, 18, 'Min Temp: %0.2f C' % to_min, color = (255, 255, 255), mono_space = False, scale = 2)\n" - " img.draw_string(4, 36, 'Max Temp: %0.2f C' % to_max, color = (255, 255, 255), mono_space = False, scale = 2)\n" - " # img.draw_string(4, 54, 'Distance: %d mm' % distance.read(), color = (255, 255, 255), mono_space = False, scale = 2)\n" + " # Draw ambient, min and max temperatures.\n" + " img.draw_string(4, 0, 'Lepton Temp: %0.2f C' % ta,\n" + " color=(255, 255, 255), mono_space=False, scale=2)\n" + " img.draw_string(4, 18, 'Min Temp: %0.2f C' % to_min,\n" + " color=(255, 255, 255), mono_space=False, scale=2)\n" + " img.draw_string(4, 36, 'Max Temp: %0.2f C' % to_max,\n" + " color=(255, 255, 255), mono_space=False, scale=2)\n" "\n" - " lcd.write(img, x_size=lcd.width(), hint=image.BILINEAR)\n" + " lcd.write(img, hint=(image.BILINEAR | image.CENTER | image.SCALE_ASPECT_KEEP))\n" "\n" - "try:\n" - " main()\n" - "except OSError:\n" - "\n" - " # I2C Bus may be stuck\n" - " p = pyb.Pin('P4', pyb.Pin.OUT_OD)\n" - " for i in range(20000):\n" - " p.value(not p.value())\n" - "\n" - " pyb.hard_reset()\n" ;