Camera (picamera2)
The Camera Module 3 plugs into the CSI ribbon connector; in circuit.py you wire pi.CSI to the camera's CSI pin and that is the whole circuit. On the software side, Picamera2 is the current camera library for the Pi — the old picamera does not run on current Raspberry Pi OS. PyRasp provides an implementation of Picamera2's common API. The official manual is Raspberry Pi's Picamera2 manual (PDF); the source lives at github.com/raspberrypi/picamera2.
Taking a photo
from wiring import *
pi = Pi()
camera = Camera()
pi.CSI >> camera.csifrom picamera2 import Picamera2
from time import sleep
camera = Picamera2()
camera.configure(camera.create_still_configuration())
camera.start()
camera.capture_file("photo.jpg")
camera.stop()
sleep(1)capture_file() writes a JPEG or PNG into the Pi's home folder (/home/pi), chosen from the file extension, and in Lab mode the Files panel shows what was captured. Without the camera wired, Picamera2() raises IndexError: list index out of range, the same as the real library with no camera connected.
Capturing to memory
capture_array() returns a NumPy array of the frame; capture_image() returns a PIL image:
import numpy as np
from picamera2 import Picamera2
camera = Picamera2()
camera.configure(camera.create_preview_configuration())
camera.start()
frame = camera.capture_array() # height × width × channels
print(frame.shape, frame.dtype)
print(frame.mean()) # average brightness, 0 … 255
from PIL import Image
image = camera.capture_image()
image.save("from_pil.png")
camera.stop() # or camera.close()
capture_array() needs NumPy and capture_image() needs Pillow; both are available in the app.
Configurations and metadata
camera = Picamera2()
still = camera.create_still_configuration(main={"size": (1920, 1080)})
camera.configure(still)
camera.start()
metadata = camera.capture_file("shot.jpg")
print(metadata["SensorTimestamp"], metadata["ExposureTime"], metadata["Lux"])
camera.stop()
There are the three usual constructors — create_preview_configuration(), create_still_configuration() and create_video_configuration() — and configure() also accepts the strings "preview", "still" and "video". set_controls() updates the camera's controls. capture_metadata() returns a small dict with SensorTimestamp (nanoseconds on the simulated clock), ExposureTime, AnalogueGain, Lux and ColourTemperature.
The high-level one-liner works too:
Picamera2().start_and_capture_file("quick.jpg", delay=1)
Going deeper
The simulated camera is a Sony IMX708 with a 4608×2592 sensor. Frames are rendered by the page at up to 1920×1080; a larger requested size (the still configuration's full sensor size, for example) is scaled down keeping the aspect ratio, so the saved 12 MP "still" is really 1920×1080. The array format follows the stream configuration: the default preview is XBGR8888 (RGBA), BGR888 gives [R, G, B] and RGB888 gives [B, G, R], matching Picamera2's little-endian naming convention.
start_preview() and stop_preview() do nothing: there is no window in the simulator, and the camera's picture source (a test scene, the webcam, or an image) is chosen where the camera is configured in Lab mode. Starting the camera also lights the module's activity LED in the board view.
Simulator vs real hardware
- Frames are rendered, not photographed. The page draws the picture the camera "sees" from the configured source — the same scene at every sensor mode. A real sensor would expose RAW modes, autofocus, HDR and rotation;
libcamera.Transformis stored but does not transform pixels, and controls likeAfMode/AwbModeare accepted as values only. - Only
Picamera2andPrevieware provided. There is nocapture_requestloop, noMJPEGEncoder/H264Encoder, noFileOutput, nostart_recording()and no multi-camera synchronisation;Preview.NULL/DRM/QT/QTGLconstants exist for imports.global_camera_info()always reports the one IMX708 even when nothing is wired — usePicamera2()itself to check the ribbon. - A missing camera fails like hardware.
Picamera2()without a camera on the CSI connector raisesIndexError: list index out of range. - Files land in the run's home folder. Photos go to
/home/piand appear in the Lab's Files panel; so do file-like objects passed tocapture_file(). Each Run is a fresh Pi, so photos do not survive to the next run. - In judged runs the camera is a grey frame. When your code is checked by the judge ("Run tests", contest submissions) the page is not there to draw anything:
capture_array()returns an all-128 RGBA field andcapture_file()saves a minimal JPEG (SOI/EOI markers). Objective tests must therefore not rely on pixel values; in the sandbox and Lab the frame is a real rendered image.