added auto exposure

This commit is contained in:
yair
2025-11-16 04:00:14 +02:00
parent acbd8ec416
commit 6654b99eab
4 changed files with 118 additions and 15 deletions

View File

@@ -15,6 +15,8 @@ Usage:
uv run scripts/camera_control.py set-framerate 30 # Set framerate to 30fps
uv run scripts/camera_control.py get-gain # Get current gain
uv run scripts/camera_control.py set-gain 50 # Set gain to 50
uv run scripts/camera_control.py get-auto-exposure # Get auto-exposure status
uv run scripts/camera_control.py set-auto-exposure 1 # Enable auto-exposure
uv run scripts/camera_control.py status # Get pipeline status
This script provides both individual control commands and full test suite functionality
@@ -182,6 +184,8 @@ Examples:
%(prog)s set-framerate 30 # Set framerate to 30fps
%(prog)s get-gain # Get current gain
%(prog)s set-gain 50 # Set gain to 50
%(prog)s get-auto-exposure # Get auto-exposure status
%(prog)s set-auto-exposure 1 # Enable auto-exposure
%(prog)s status # Get pipeline status
""",
formatter_class=argparse.RawDescriptionHelpFormatter
@@ -190,7 +194,7 @@ Examples:
parser.add_argument('command',
nargs='?',
choices=['test', 'get-exposure', 'set-exposure', 'get-framerate', 'set-framerate',
'get-gain', 'set-gain', 'status'],
'get-gain', 'set-gain', 'get-auto-exposure', 'set-auto-exposure', 'status'],
help='Command to execute')
parser.add_argument('value',
@@ -259,6 +263,22 @@ Examples:
sys.exit(1)
success = simple_command(f"SET_GAIN {gain_value}", f"Setting gain to {gain_value}")
elif args.command == 'get-auto-exposure':
success = simple_command("GET_AUTO_EXPOSURE", "Getting auto-exposure status")
elif args.command == 'set-auto-exposure':
if args.value is None:
print("Error: set-auto-exposure requires a value (0=off, 1=on)")
parser.print_help()
sys.exit(1)
# Convert to int
ae_value = int(args.value)
if ae_value not in [0, 1]:
print("Error: Auto-exposure must be 0 (off) or 1 (on)")
sys.exit(1)
success = simple_command(f"SET_AUTO_EXPOSURE {ae_value}",
f"{'Enabling' if ae_value else 'Disabling'} auto-exposure")
elif args.command == 'status':
success = simple_command("STATUS", "Getting pipeline status")

View File

@@ -26,7 +26,9 @@
# - Configurable video streaming (default: UDP port 5000 to 127.0.0.1)
# - Optional control interface (default: UDP port 5001 on 0.0.0.0)
# - Dynamic exposure control (0.015-30000 milliseconds, default: 10ms)
# - Auto-exposure mode support (--auto-exposure flag)
# - Dynamic framerate control (1-20000 fps, default: 750fps)
# - Dynamic gain control (0-100, 0 for auto, default: 0)
# - Dynamic camera ID selection (0-254, default: 0 for first found)
# - Dynamic device ID selection (0-254, system enumeration ID)
# - Configurable video cropping (default: crop 3 pixels from bottom)
@@ -40,11 +42,13 @@
# GET_FRAMERATE - Get current framerate
# SET_CAMERA_ID <value> - Set camera ID (0-254, 0 is first found)
# GET_CAMERA_ID - Get current camera ID
# SET_DEVICE_ID <value> - Set device ID (0-254, system enumeration)
# GET_DEVICE_ID - Get current device ID
# SET_GAIN <value> - Set master gain (0-100, 0 for auto)
# GET_GAIN - Get current gain value
# STATUS - Get pipeline status and current settings
# SET_DEVICE_ID <value> - Set device ID (0-254, system enumeration)
# GET_DEVICE_ID - Get current device ID
# SET_GAIN <value> - Set master gain (0-100, 0 for auto)
# GET_GAIN - Get current gain value
# SET_AUTO_EXPOSURE <0|1> - Enable (1) or disable (0) auto-exposure
# GET_AUTO_EXPOSURE - Get auto-exposure status
# STATUS - Get pipeline status and current settings
#
# Example Control Usage:
# echo "SET_EXPOSURE 10" | nc -u 127.0.0.1 5001
@@ -134,7 +138,7 @@ class ControlServer:
print(f"Control server listening on UDP port {self.port}")
print(" Commands: SET_EXPOSURE <val>, GET_EXPOSURE, SET_FRAMERATE <val>, GET_FRAMERATE,")
print(" SET_CAMERA_ID <val>, GET_CAMERA_ID, SET_DEVICE_ID <val>, GET_DEVICE_ID,")
print(" SET_GAIN <val>, GET_GAIN, STATUS")
print(" SET_GAIN <val>, GET_GAIN, SET_AUTO_EXPOSURE <0|1>, GET_AUTO_EXPOSURE, STATUS")
while self.running:
try:
@@ -192,6 +196,10 @@ class ControlServer:
return self.handle_set_gain(parts)
elif cmd == "GET_GAIN":
return self.handle_get_gain()
elif cmd == "SET_AUTO_EXPOSURE":
return self.handle_set_auto_exposure(parts)
elif cmd == "GET_AUTO_EXPOSURE":
return self.handle_get_auto_exposure()
elif cmd == "STATUS":
return self.handle_status()
else:
@@ -336,6 +344,33 @@ class ControlServer:
except Exception as e:
return f"ERROR: {str(e)}"
def handle_set_auto_exposure(self, parts):
"""Handle SET_AUTO_EXPOSURE command"""
if len(parts) != 2:
return "ERROR INVALID_SYNTAX: Usage: SET_AUTO_EXPOSURE <0|1>"
try:
value = int(parts[1])
if value not in [0, 1]:
return "ERROR OUT_OF_RANGE: Auto-exposure must be 0 (off) or 1 (on)"
self.src.set_property("auto-exposure", bool(value))
actual = self.src.get_property("auto-exposure")
return f"OK {int(actual)}"
except ValueError:
return "ERROR INVALID_SYNTAX: Auto-exposure must be 0 or 1"
except Exception as e:
return f"ERROR: {str(e)}"
def handle_get_auto_exposure(self):
"""Handle GET_AUTO_EXPOSURE command"""
try:
value = self.src.get_property("auto-exposure")
return f"OK {int(value)}"
except Exception as e:
return f"ERROR: {str(e)}"
def handle_status(self):
"""Handle STATUS command"""
try:
@@ -344,6 +379,7 @@ class ControlServer:
camera_id = self.src.get_property("camera-id")
device_id = self.src.get_property("device-id")
gain = self.src.get_property("gain")
auto_exposure = int(self.src.get_property("auto-exposure"))
# Get pipeline state
state = "UNKNOWN"
@@ -351,7 +387,7 @@ class ControlServer:
_, current_state, _ = self.pipeline.get_state(0)
state = current_state.value_nick.upper()
return f"OK exposure={exposure} framerate={framerate} camera_id={camera_id} device_id={device_id} gain={gain} state={state}"
return f"OK exposure={exposure} framerate={framerate} camera_id={camera_id} device_id={device_id} gain={gain} auto_exposure={auto_exposure} state={state}"
except Exception as e:
return f"ERROR: {str(e)}"
@@ -424,6 +460,11 @@ Examples:
metavar='GAIN',
help='Master gain (0-100, 0 for auto/default)'
)
camera_group.add_argument(
'--auto-exposure',
action='store_true',
help='Enable automatic exposure control'
)
# Video processing
video_group = parser.add_argument_group('Video Processing')
@@ -576,6 +617,9 @@ src.set_property("device-id", args.device_id)
# Gain (0 for auto/default)
src.set_property("gain", args.gain)
# Auto-exposure
src.set_property("auto-exposure", args.auto_exposure)
# Video crop to remove bottom pixels (if enabled)
elements_to_link = [src]
if args.crop_bottom > 0: