Multi-Camera Operation
Relevant source files
The following files were used as context for generating this wiki page:The picamera2 library provides the ability to control multiple Picamera2 objects within the same Python process. This allows for applications such as multi-angle previews, stereo vision, and synchronized captures or recordings from several cameras simultaneously. The feature was introduced in version 0.3.6, with software-based frame synchronization added in version 0.3.25.
Each camera is managed through its own Picamera2 instance, allowing for independent configuration, preview windows, and control. For coordinated actions, a software-based synchronization mechanism is available, enabling applications to capture frames from multiple cameras at nearly the same time.
Sources: CHANGELOG.md:18, 252-254
Core Architecture
Multi-camera support is managed by the CameraManager class, which acts as a singleton to handle all attached camera devices. When a Picamera2 object is instantiated, it registers itself with this central manager.
Sources: picamera2/picamera2.py:79-81
CameraManager and Picamera2 Relationship
The CameraManager maintains a dictionary of active Picamera2 instances, indexed by their camera number. It runs a background thread to listen for events from libcamera, such as completed requests, and dispatches them to the correct Picamera2 instance.
This diagram shows the CameraManager singleton managing multiple Picamera2 instances.
Sources: picamera2/picamera2.py:79-142
Discovering and Initializing Cameras
Before initializing cameras, you can get information about all attached devices using the static method Picamera2.global_camera_info(). This method returns a list of dictionaries, each containing details about a camera, including its model, ID, and numerical index (Num).
This numerical index can then be passed to the Picamera2 constructor to open a specific camera.
Sources: picamera2/picamera2.py:228-242, 271-274
The general workflow for initializing multiple cameras is as follows:
This flowchart illustrates the steps to initialize and start multiple cameras.
Sources: examples/multicamera_preview.py:10-15
Example: Initialization
The following snippet demonstrates how to get the list of cameras and create a Picamera2 object for each one.
# examples/multicamera_preview.py:10-15
cam_infos = Picamera2.global_camera_info()
if len(cam_infos) < 2:
print("Need at least two cameras attached")
exit()
picam2_0 = Picamera2(0)
picam2_1 = Picamera2(1)
Sources: examples/multicamera_preview.py:10-15
Independent Operation
Once initialized, each Picamera2 object can be configured and operated independently. This is useful for applications that need to display feeds from multiple cameras without requiring strict synchronization. For example, you can start a separate preview window for each camera.
Sources: examples/multicamera_preview.py:17-26
Example: Multiple Previews
The multicamera_preview.py example shows how to create and start two independent preview windows. Each camera is configured and started separately, and each has its own preview running in a loop.
# examples/multicamera_preview.py:17-26
picam2_0.configure(picam2_0.create_preview_configuration())
picam2_0.start_preview(Preview.QTGL, x=100, y=200, width=600, height=400)
picam2_0.start()
picam2_1.configure(picam2_1.create_preview_configuration())
picam2_1.start_preview(Preview.QTGL, x=800, y=200, width=600, height=400)
picam2_1.start()
# Loop to keep previews running
while True:
time.sleep(1)
Sources: examples/multicamera_preview.py:17-26
Software Frame Synchronization
For applications like stereo vision, synchronized capture is crucial. picamera2 implements a software-based frame synchronization mechanism using a master/slave (or server/client) model.
Sources: CHANGELOG.md:18, examples/sync_capture.py:10-11
Configuration
Synchronization is configured via camera controls. One camera must be designated as the Server, and all others as Client. All cameras must point to the same SyncDevice, which is a temporary file used for communication.
| Control | Description | Values |
|---|---|---|
SyncMode | Sets the synchronization role of the camera. | SyncModeEnum.Server, SyncModeEnum.Client |
SyncDevice | A file path used for inter-process communication between the server and client cameras. Must be the same for all cameras in a sync group. | e.g., "/tmp/cam_sync" |
Sources: examples/sync_capture.py:23-25, tests/sync_test.py:16-17
Synchronized Capture
After starting the cameras, applications should use the capture_sync_request() method instead of capture_request(). This method waits until a synchronized frame is available. The first few frames may not be synchronized; applications can check the SyncReady flag in the frame's metadata to confirm synchronization status.
The capture_sync_request_() internal method checks the SyncReady metadata field of each completed request. If a request is not ready, it is discarded, and the method waits for the next one.
Sources: picamera2/picamera2.py:1330-1345
The synchronization sequence is as follows:
- The application configures one camera as
Serverand others asClient. - The server camera is started first. It waits for clients to connect.
- Client cameras are started. They connect to the server via the
SyncDevice. - Once all cameras are connected and synchronized, the
SyncReadymetadata flag is set toTrueon their respective frame requests. - The application calls
capture_sync_request()on each camera to retrieve synchronized frames.
This sequence diagram shows the setup and capture flow for synchronized cameras.
Sources: examples/sync_capture.py, picamera2/picamera2.py:1330-1345
Example: Synchronized Still Images
The sync_capture.py example demonstrates capturing synchronized still images from two cameras and saving them.
# examples/sync_capture.py:22-31
# Must be done before configure.
picam2_0.set_controls({"SyncMode": SyncModeEnum.Server, "SyncDevice": "/tmp/cam_sync"})
picam2_1.set_controls({"SyncMode": SyncModeEnum.Client, "SyncDevice": "/tmp/cam_sync"})
picam2_0.configure("still")
picam2_1.configure("still")
picam2_0.start()
picam2_1.start()
time.sleep(1) # Give cameras time to sync
After setup, synchronized requests are captured in a loop.
# examples/sync_capture.py:36-41
req0 = picam2_0.capture_sync_request()
req1 = picam2_1.capture_sync_request()
req0.save("main", "sync_capture0.jpg")
req1.save("main", "sync_capture1.jpg")
Sources: examples/sync_capture.py:22-41
Example: Synchronized Video Recording
The sync_recording.py example extends the concept to video. It sets up synchronization, starts encoders for each camera, and then captures synchronized requests in a loop, feeding each frame to the respective encoder.
# examples/sync_recording.py:36-44
picam2_0.start_encoder(H264Encoder(10000000), "sync_video0.h264")
picam2_1.start_encoder(H264Encoder(10000000), "sync_video1.h264")
# The requests will be delivered to the encoder automatically.
for i in range(200): # capture 200 frames
req0 = picam2_0.capture_sync_request()
req0.release()
req1 = picam2_1.capture_sync_request()
req1.release()
Sources: examples/sync_recording.py:36-44
Summary
picamera2 offers robust support for multi-camera systems. Users can discover and initialize multiple cameras, controlling them independently for tasks like multi-angle monitoring. For more advanced applications requiring temporal alignment, the software frame synchronization feature provides a powerful way to capture or record from multiple cameras simultaneously, opening up possibilities for stereo imaging and other computer vision tasks. The implementation is managed through the central CameraManager and configured using standard camera controls, making it a well-integrated part of the library.
Sources: picamera2/picamera2.py, examples/sync_capture.py, examples/multicamera_preview.py