CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/pypi-picamera2

The libcamera-based Python interface to Raspberry Pi cameras, based on the original Picamera library

Pending
Overview
Eval results
Files

controls.mddocs/

Camera Controls

Advanced camera control system for setting exposure, gain, white balance, focus, and other camera parameters. The controls system provides both immediate parameter adjustment and thread-safe access for real-time applications.

Capabilities

Control Setting

Set camera controls individually or in groups with immediate effect.

def set_controls(self, controls: dict):
    """
    Set multiple camera controls.
    
    Parameters:
    - controls: dict, control name to value mapping
      Common controls include:
      - ExposureTime: int, exposure time in microseconds
      - AnalogueGain: float, analog gain multiplier
      - DigitalGain: float, digital gain multiplier  
      - Brightness: float, brightness adjustment (-1.0 to 1.0)
      - Contrast: float, contrast adjustment (0.0 to 10.0)
      - Saturation: float, saturation adjustment (0.0 to 10.0)
      - AwbEnable: bool, automatic white balance enable
      - AwbMode: int, white balance mode
      - AeEnable: bool, automatic exposure enable
      - AeExposureMode: int, exposure mode
      - AfMode: int, autofocus mode
      - AfTrigger: int, autofocus trigger
    
    Raises:
    - RuntimeError: If control values are invalid or out of range
    """

Controls Class

Thread-safe controls interface for real-time parameter adjustment.

class Controls:
    """Thread-safe camera controls interface."""
    
    def __init__(self, picam2: Picamera2, controls: dict = None):
        """
        Initialize Controls object.
        
        Parameters:
        - picam2: Picamera2 instance
        - controls: dict, initial control values
        """
    
    def set_controls(self, controls: dict):
        """
        Update multiple controls from dictionary.
        
        Parameters:
        - controls: dict or Controls object with new values
        """
    
    def __setattr__(self, name: str, value):
        """
        Set individual control using attribute syntax.
        
        Parameters:
        - name: str, control name
        - value: control value
        
        Example:
        controls.ExposureTime = 10000
        controls.AnalogueGain = 2.0
        """
    
    def __getattribute__(self, name: str):
        """
        Get control value using attribute syntax.
        
        Returns:
        Current control value or raises AttributeError if not found
        """
    
    def __enter__(self):
        """Context manager entry for thread-safe access."""
        return self
    
    def __exit__(self, exc_type, exc_val, exc_tb):
        """Context manager exit for thread-safe access."""
    
    def get_libcamera_controls(self) -> dict:
        """
        Convert to libcamera control format.
        
        Returns:
        dict: Controls in libcamera format
        """
    
    def make_dict(self) -> dict:
        """
        Convert to standard dictionary.
        
        Returns:
        dict: Control name to value mapping
        """

Virtual Control Fields

Special control fields that provide convenient access to complex parameters.

# FrameRate virtual field
@property
def FrameRate(self) -> float:
    """
    Frame rate in frames per second (virtual field).
    Maps to FrameDurationLimits with automatic conversion.
    
    Setting this adjusts both minimum and maximum frame durations.
    """

@FrameRate.setter
def FrameRate(self, fps: float):
    """Set frame rate, converting to FrameDurationLimits."""

Common Control Parameters

Exposure Controls

# Exposure time in microseconds
ExposureTime: int  # Range typically 10-60000000 depending on sensor

# Automatic exposure enable
AeEnable: bool  # True for auto, False for manual

# Exposure mode
AeExposureMode: int
# Common values:
# 0: Normal
# 1: Short 
# 2: Long
# 3: Custom

# Exposure compensation
ExposureValue: float  # Range typically -8.0 to 8.0 in EV units

# Metering mode
AeMeteringMode: int
# Common values:
# 0: Centre-weighted
# 1: Spot
# 2: Matrix

Gain Controls

# Analog gain multiplier
AnalogueGain: float  # Range typically 1.0-16.0

# Digital gain multiplier  
DigitalGain: float  # Range typically 1.0-64.0

# Overall gain
Gain: float  # Combined analog and digital gain

White Balance Controls

# Automatic white balance enable
AwbEnable: bool

# White balance mode
AwbMode: int
# Common values:
# 0: Auto
# 1: Incandescent
# 2: Tungsten
# 3: Fluorescent
# 4: Indoor
# 5: Daylight
# 6: Cloudy

# Manual color gains (when AwbEnable=False)
ColourGains: tuple[float, float]  # (red_gain, blue_gain)

Focus Controls

# Autofocus mode
AfMode: int
# Common values:
# 0: Manual
# 1: Auto
# 2: Continuous

# Autofocus trigger
AfTrigger: int
# Values:
# 0: Idle
# 1: Start
# 2: Cancel

# Manual focus position (when AfMode=0)
LensPosition: float  # Range 0.0-10.0 typically

Image Enhancement

# Brightness adjustment
Brightness: float  # Range -1.0 to 1.0

# Contrast adjustment
Contrast: float  # Range 0.0 to 10.0, 1.0 = normal

# Saturation adjustment
Saturation: float  # Range 0.0 to 10.0, 1.0 = normal

# Sharpness adjustment  
Sharpness: float  # Range 0.0 to 10.0, 1.0 = normal

Usage Examples

Basic Control Setting

from picamera2 import Picamera2

picam2 = Picamera2()
picam2.configure(picam2.create_preview_configuration())
picam2.start()

# Set controls using dictionary
picam2.set_controls({
    "ExposureTime": 20000,  # 20ms exposure
    "AnalogueGain": 2.0,    # 2x gain
    "AwbEnable": False,     # Manual white balance
    "ColourGains": (1.2, 1.8)  # Red and blue gains
})

# Check available controls
print("Available controls:")
for control, info in picam2.camera_controls.items():
    print(f"  {control}: {info}")

picam2.close()

Using Controls Class

from picamera2 import Picamera2, Controls

picam2 = Picamera2()
picam2.configure(picam2.create_preview_configuration())
picam2.start()

# Create controls object
controls = Controls(picam2)

# Set controls using attribute syntax
controls.ExposureTime = 10000
controls.AnalogueGain = 1.5
controls.Brightness = 0.1

# Apply all changes
picam2.set_controls(controls)

# Or use context manager for thread safety
with controls:
    controls.ExposureTime = 30000
    controls.AnalogueGain = 3.0
    # Changes applied automatically on exit

picam2.close()

Manual Exposure Control

from picamera2 import Picamera2
import time

picam2 = Picamera2()
picam2.configure(picam2.create_still_configuration())
picam2.start()

# Disable automatic exposure
picam2.set_controls({
    "AeEnable": False,
    "ExposureTime": 5000,   # 5ms
    "AnalogueGain": 1.0
})

# Take bracket of exposures
exposures = [1000, 5000, 10000, 20000, 50000]
for i, exp_time in enumerate(exposures):
    picam2.set_controls({"ExposureTime": exp_time})
    time.sleep(0.1)  # Allow settling
    picam2.capture_file(f"exposure_{exp_time}us.jpg")

picam2.close()

White Balance Control

from picamera2 import Picamera2

picam2 = Picamera2()
picam2.configure(picam2.create_preview_configuration())
picam2.start()

# Try different white balance modes
wb_modes = {
    "auto": {"AwbEnable": True, "AwbMode": 0},
    "daylight": {"AwbEnable": True, "AwbMode": 5},
    "tungsten": {"AwbEnable": True, "AwbMode": 2},
    "manual_warm": {"AwbEnable": False, "ColourGains": (1.5, 1.2)},
    "manual_cool": {"AwbEnable": False, "ColourGains": (1.0, 2.0)}
}

for name, settings in wb_modes.items():
    picam2.set_controls(settings)
    time.sleep(1)  # Allow white balance to settle
    picam2.capture_file(f"wb_{name}.jpg")

picam2.close()

Focus Control

from picamera2 import Picamera2
import time

picam2 = Picamera2()
picam2.configure(picam2.create_preview_configuration())
picam2.start()

# Enable continuous autofocus
picam2.set_controls({
    "AfMode": 2,  # Continuous AF
    "AfTrigger": 0  # Idle
})

# Wait for focus to settle
time.sleep(2)

# Trigger single autofocus
picam2.set_controls({"AfTrigger": 1})  # Start AF
time.sleep(1)  # Wait for focus
picam2.capture_file("autofocus.jpg")

# Manual focus sweep
picam2.set_controls({"AfMode": 0})  # Manual focus
focus_positions = [0.5, 1.0, 2.0, 5.0, 10.0]
for pos in focus_positions:
    picam2.set_controls({"LensPosition": pos})
    time.sleep(0.5)
    picam2.capture_file(f"focus_{pos:.1f}.jpg")

picam2.close()

Real-time Control Adjustment

from picamera2 import Picamera2, Controls
import time

picam2 = Picamera2()
picam2.configure(picam2.create_preview_configuration())
picam2.start()

controls = Controls(picam2)

# Slowly increase exposure
for exp in range(1000, 50000, 1000):
    controls.ExposureTime = exp
    picam2.set_controls(controls)
    time.sleep(0.1)
    
    # Could capture frame or analyze preview here
    print(f"Exposure: {exp}us")

picam2.close()

Frame Rate Control

from picamera2 import Picamera2, Controls

picam2 = Picamera2()
config = picam2.create_video_configuration()
picam2.configure(config)
picam2.start()

controls = Controls(picam2)

# Set frame rate using virtual field
controls.FrameRate = 30.0  # 30 fps
picam2.set_controls(controls)

# Or set manually using frame duration
picam2.set_controls({
    "FrameDurationLimits": (33333, 33333)  # 30fps (33.33ms per frame)
})

picam2.close()

Install with Tessl CLI

npx tessl i tessl/pypi-picamera2

docs

advanced.md

capture.md

configuration.md

controls.md

core-operations.md

index.md

preview.md

recording.md

tile.json