diff --git a/scripts/examples/01-Camera/03-Event-Cameras/02-Genx320/genx320_grayscale_led_tracking.py b/scripts/examples/01-Camera/03-Event-Cameras/02-Genx320/genx320_grayscale_led_tracking.py new file mode 100644 index 000000000..caedec5aa --- /dev/null +++ b/scripts/examples/01-Camera/03-Event-Cameras/02-Genx320/genx320_grayscale_led_tracking.py @@ -0,0 +1,37 @@ +# 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 +# +# This example shows off using the GenX320 event sensor from Prophesee for tracking an active marker +# with LEDs. The sensor settings (biases) are tuned for seeing only high-contrast LEDs modulated at +# high frequency. With these settings, the sensor does not detect any low-contrast changes in +# the scene except of LEDs thus allowing highly efficient and robust LEDs tracking. +# Prophesee active marker board with LEDs and the corresponding event-based data are shown in +# https://youtu.be/j-LpkDpCxUU?si=jA3B4xZg9RHlyoW3. + +import sensor +import time + +sensor.reset() +sensor.set_pixformat(sensor.GRAYSCALE) # Must always be grayscale. +sensor.set_framesize(sensor.B320X320) # Must always be 320x320. +sensor.set_framerate(200) +# Applies sensor biases tuned for tracking of an active marker with LEDs +sensor.ioctl(sensor.IOCTL_GENX320_SET_BIASES, sensor.GENX320_BIASES_ACTIVE_MARKER) + +clock = time.clock() + +while True: + clock.tick() + + img = sensor.snapshot() + + blobs = img.find_blobs( + [(120, 140)], invert=True, pixels_threshold=2, area_threshold=4, merge=True + ) + + for blob in blobs: + img.draw_rectangle(blob.rect(), color=(255, 255, 255)) + img.draw_cross(blob.cx(), blob.cy(), color=(0, 0, 0)) + + print(clock.fps()) diff --git a/src/omv/common/omv_csi.h b/src/omv/common/omv_csi.h index 89a66c9b3..1d0d33d23 100644 --- a/src/omv/common/omv_csi.h +++ b/src/omv/common/omv_csi.h @@ -218,7 +218,8 @@ typedef enum { OMV_CSI_IOCTL_HIMAX_MD_WINDOW = 0x1C | OMV_CSI_IOCTL_FLAGS_ABORT, OMV_CSI_IOCTL_HIMAX_MD_THRESHOLD = 0x1D, OMV_CSI_IOCTL_HIMAX_OSC_ENABLE = 0x1E | OMV_CSI_IOCTL_FLAGS_ABORT, - OMV_CSI_IOCTL_GET_RGB_STATS = 0x1F + OMV_CSI_IOCTL_GET_RGB_STATS = 0x1F, + OMV_CSI_IOCTL_GENX320_SET_BIASES = 0x20 } omv_csi_ioctl_t; typedef enum { @@ -245,6 +246,16 @@ typedef enum { OMV_CSI_ERROR_JPEG_OVERFLOW = -20, } omv_csi_error_t; +#if (OMV_GENX320_ENABLE == 1) +typedef enum { + OMV_CSI_GENX320_BIASES_DEFAULT, + OMV_CSI_GENX320_BIASES_LOW_LIGHT, + OMV_CSI_GENX320_BIASES_ACTIVE_MARKER, + OMV_CSI_GENX320_BIASES_LOW_NOISE, + OMV_CSI_GENX320_BIASES_HIGH_SPEED +} omv_csi_genx320_biases_preset_t; +#endif + typedef void (*vsync_cb_t) (uint32_t vsync); typedef void (*frame_cb_t) (); typedef struct _omv_csi omv_csi_t; diff --git a/src/omv/modules/py_csi.c b/src/omv/modules/py_csi.c index 8139bbc18..442010181 100644 --- a/src/omv/modules/py_csi.c +++ b/src/omv/modules/py_csi.c @@ -1015,6 +1015,15 @@ static mp_obj_t py_omv_csi_ioctl(uint n_args, const mp_obj_t *args) { break; } + #if (OMV_GENX320_ENABLE == 1) + case OMV_CSI_IOCTL_GENX320_SET_BIASES: { + if (n_args == 2) { + error = omv_csi_ioctl(request, mp_obj_get_int(args[1])); + } + break; + } + #endif // (OMV_GENX320_ENABLE == 1) + default: { omv_csi_raise_error(OMV_CSI_ERROR_CTL_UNSUPPORTED); break; @@ -1207,6 +1216,15 @@ static const mp_rom_map_elem_t globals_dict_table[] = { #endif { MP_ROM_QSTR(MP_QSTR_IOCTL_GET_RGB_STATS), MP_ROM_INT(OMV_CSI_IOCTL_GET_RGB_STATS)}, + #if (OMV_GENX320_ENABLE == 1) + { MP_ROM_QSTR(MP_QSTR_IOCTL_GENX320_SET_BIASES), MP_ROM_INT(OMV_CSI_IOCTL_GENX320_SET_BIASES)}, + { MP_ROM_QSTR(MP_QSTR_GENX320_BIASES_DEFAULT), MP_ROM_INT(OMV_CSI_GENX320_BIASES_DEFAULT)}, + { MP_ROM_QSTR(MP_QSTR_GENX320_BIASES_LOW_LIGHT), MP_ROM_INT(OMV_CSI_GENX320_BIASES_LOW_LIGHT)}, + { MP_ROM_QSTR(MP_QSTR_GENX320_BIASES_ACTIVE_MARKER), MP_ROM_INT(OMV_CSI_GENX320_BIASES_ACTIVE_MARKER)}, + { MP_ROM_QSTR(MP_QSTR_GENX320_BIASES_LOW_NOISE), MP_ROM_INT(OMV_CSI_GENX320_BIASES_LOW_NOISE)}, + { MP_ROM_QSTR(MP_QSTR_GENX320_BIASES_HIGH_SPEED), MP_ROM_INT(OMV_CSI_GENX320_BIASES_HIGH_SPEED)}, + #endif + // Sensor functions { MP_ROM_QSTR(MP_QSTR___init__), MP_ROM_PTR(&py_omv_csi__init__obj) }, { MP_ROM_QSTR(MP_QSTR_reset), MP_ROM_PTR(&py_omv_csi_reset_obj) }, diff --git a/src/omv/sensors/genx320.c b/src/omv/sensors/genx320.c index b7883e68c..327290d0c 100644 --- a/src/omv/sensors/genx320.c +++ b/src/omv/sensors/genx320.c @@ -431,6 +431,80 @@ static int snapshot(omv_csi_t *csi, image_t *image, uint32_t flags) { return ret; } +static int ioctl(omv_csi_t *csi, int request, va_list ap) { + int ret = 0; + + switch (request) { + // Setting a preset of biases tuned for a particular application/condition + case OMV_CSI_IOCTL_GENX320_SET_BIASES: { + int mode = va_arg(ap, int); + switch (mode) { + case OMV_CSI_GENX320_BIASES_DEFAULT: { + // Set default biases V2.0.0 + psee_sensor_set_bias(DIFF, 51); + psee_sensor_set_bias(DIFF_OFF, 28); + psee_sensor_set_bias(DIFF_ON, 25); + psee_sensor_set_bias(FO, 34); + psee_sensor_set_bias(HPF, 40); + psee_sensor_set_bias(REFR, 10); + break; + } + case OMV_CSI_GENX320_BIASES_LOW_LIGHT: { + // Set biases tuned for low light + psee_sensor_set_bias(DIFF, 51); + psee_sensor_set_bias(DIFF_OFF, 19); + psee_sensor_set_bias(DIFF_ON, 24); + psee_sensor_set_bias(FO, 19); + psee_sensor_set_bias(HPF, 0); + psee_sensor_set_bias(REFR, 10); + break; + } + case OMV_CSI_GENX320_BIASES_ACTIVE_MARKER: { + // Set biases tuned for active marker + psee_sensor_set_bias(DIFF, 51); + psee_sensor_set_bias(DIFF_OFF, 45); //127 + psee_sensor_set_bias(DIFF_ON, 55); //78 + psee_sensor_set_bias(FO, 50); + psee_sensor_set_bias(HPF, 127); + psee_sensor_set_bias(REFR, 0); + break; + } + case OMV_CSI_GENX320_BIASES_LOW_NOISE: { + // Set low sensitivity low noise biases + psee_sensor_set_bias(DIFF, 51); + psee_sensor_set_bias(DIFF_OFF, 38); + psee_sensor_set_bias(DIFF_ON, 35); + psee_sensor_set_bias(FO, 24); + psee_sensor_set_bias(HPF, 40); + psee_sensor_set_bias(REFR, 10); + break; + } + case OMV_CSI_GENX320_BIASES_HIGH_SPEED: { + // Set biases tuned for high speed motion + psee_sensor_set_bias(DIFF, 51); + psee_sensor_set_bias(DIFF_OFF, 26); + psee_sensor_set_bias(DIFF_ON, 37); + psee_sensor_set_bias(FO, 38); + psee_sensor_set_bias(HPF, 74); + psee_sensor_set_bias(REFR, 25); + break; + } + default: { + ret = -1; + break; + } + } + break; + } + default: { + ret = -1; + break; + } + } + + return ret; +} + int genx320_init(omv_csi_t *csi) { // Initialize csi structure csi->reset = reset; @@ -446,6 +520,7 @@ int genx320_init(omv_csi_t *csi) { csi->set_hmirror = set_hmirror; csi->set_vflip = set_vflip; csi->snapshot = snapshot; + csi->ioctl = ioctl; // Set csi flags csi->mono_bpp = sizeof(uint8_t);