Add brightness-deadband property to intervalometer to prevent oscillation

- Add new brightness-deadband property (default 10.0, range 0.0-50.0)
- Implements deadband/tolerance zone around target brightness
- When brightness is within ±deadband, no adjustments are made
- Prevents oscillation at fast update rates (10-100ms)
- Allows fast corrections when brightness significantly deviates
- Enables fast ramp rates without flicker/oscillation
- Updated README with detailed deadband documentation and usage examples
- Solves exposure fluctuation issue at high frame rates with fast updates
This commit is contained in:
yair
2025-11-21 13:46:19 +02:00
parent 93d8da45e6
commit 45fa4c07b4
4 changed files with 106 additions and 17 deletions

View File

@@ -62,7 +62,8 @@ enum
PROP_LOG_FILE,
PROP_CAMERA_ELEMENT,
PROP_UPDATE_INTERVAL,
PROP_BRIGHTNESS_SMOOTHING
PROP_BRIGHTNESS_SMOOTHING,
PROP_BRIGHTNESS_DEADBAND
};
#define DEFAULT_PROP_ENABLED TRUE
@@ -77,6 +78,7 @@ enum
#define DEFAULT_PROP_CAMERA_ELEMENT ""
#define DEFAULT_PROP_UPDATE_INTERVAL 100 /* Update every 100ms (10 Hz) */
#define DEFAULT_PROP_BRIGHTNESS_SMOOTHING 0.1 /* 10% new, 90% history - heavy smoothing for time-lapse */
#define DEFAULT_PROP_BRIGHTNESS_DEADBAND 10.0 /* ±10 brightness units deadband zone */
/* GStreamer boilerplate */
#define gst_intervalometer_parent_class parent_class
@@ -242,6 +244,14 @@ gst_intervalometer_class_init (GstIntervalometerClass * klass)
0.0, 1.0, DEFAULT_PROP_BRIGHTNESS_SMOOTHING,
G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
g_object_class_install_property (gobject_class, PROP_BRIGHTNESS_DEADBAND,
g_param_spec_double ("brightness-deadband", "Brightness Deadband",
"Deadband zone around target brightness where no adjustments are made (0=disabled). "
"Creates a stable zone to prevent oscillation. "
"Recommended: 10.0 for fast update rates, 5.0 for slower rates, 0.0 to disable",
0.0, 50.0, DEFAULT_PROP_BRIGHTNESS_DEADBAND,
G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
/* Set element metadata */
gst_element_class_add_pad_template (gstelement_class,
gst_static_pad_template_get (&gst_intervalometer_sink_template));
@@ -278,6 +288,7 @@ gst_intervalometer_init (GstIntervalometer * filter)
filter->camera_element_name = g_strdup (DEFAULT_PROP_CAMERA_ELEMENT);
filter->update_interval = DEFAULT_PROP_UPDATE_INTERVAL;
filter->brightness_smoothing = DEFAULT_PROP_BRIGHTNESS_SMOOTHING;
filter->brightness_deadband = DEFAULT_PROP_BRIGHTNESS_DEADBAND;
/* Initialize internal state */
filter->camera_src = NULL;
@@ -350,6 +361,9 @@ gst_intervalometer_set_property (GObject * object, guint prop_id,
case PROP_BRIGHTNESS_SMOOTHING:
filter->brightness_smoothing = g_value_get_double (value);
break;
case PROP_BRIGHTNESS_DEADBAND:
filter->brightness_deadband = g_value_get_double (value);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
@@ -399,6 +413,9 @@ gst_intervalometer_get_property (GObject * object, guint prop_id,
case PROP_BRIGHTNESS_SMOOTHING:
g_value_set_double (value, filter->brightness_smoothing);
break;
case PROP_BRIGHTNESS_DEADBAND:
g_value_set_double (value, filter->brightness_deadband);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
@@ -690,6 +707,7 @@ gst_intervalometer_update_camera_settings (GstIntervalometer * filter,
{
gdouble error, adjusted_target, exposure_range, gain_range;
gdouble ramp_multiplier;
gdouble abs_error;
if (!filter->camera_src) {
return;
@@ -699,6 +717,14 @@ gst_intervalometer_update_camera_settings (GstIntervalometer * filter,
error = (filter->target_brightness - brightness) *
pow (2.0, filter->compensation);
/* Check deadband zone - if enabled and brightness is within tolerance, skip adjustments */
abs_error = fabs(filter->target_brightness - brightness);
if (filter->brightness_deadband > 0.0 && abs_error < filter->brightness_deadband) {
GST_DEBUG_OBJECT (filter, "Within deadband zone (error=%.2f < %.2f), skipping adjustment",
abs_error, filter->brightness_deadband);
return;
}
/* Adjust target brightness based on error */
adjusted_target = filter->target_brightness + error;