Skip to content

Commit bfc70bc

Browse files
Add CameraManager
1 parent 2ff264d commit bfc70bc

3 files changed

Lines changed: 276 additions & 5 deletions

File tree

docs/architecture/frameworks.md

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -246,12 +246,13 @@ Provides access to camera hardware.
246246
```python
247247
from mpos import CameraManager
248248

249-
# Initialize at startup
250-
CameraManager.init()
251-
252-
# Capture image
253-
image_data = CameraManager.capture_photo()
249+
if CameraManager.has_camera():
250+
cam = CameraManager.get_cameras()[0]
251+
cam_obj = cam.init(320, 240, "RGB565")
252+
image_data = cam.capture(cam_obj)
253+
cam.deinit(cam_obj)
254254
```
255+
See [CameraManager](../frameworks/camera-manager.md) for details.
255256

256257
### SensorManager
257258
Manages sensor access (accelerometer, gyroscope, magnetometer, temperature).

docs/frameworks/camera-manager.md

Lines changed: 269 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,269 @@
1+
# CameraManager
2+
3+
MicroPythonOS provides a centralized camera framework called **CameraManager**, inspired by Android's Camera2 API. It manages camera devices through a registry of `Camera` descriptors that encapsulate hardware-specific init, capture, deinit, and settings functions.
4+
5+
## Overview
6+
7+
CameraManager provides:
8+
9+
- **Camera registry** - Board init files register camera devices with their driver functions
10+
- **Lens facing constants** - `LENS_FACING_BACK`, `LENS_FACING_FRONT`, `LENS_FACING_EXTERNAL`
11+
- **Resolution mapping** - Map pixel dimensions to ESP32 `FrameSize` enum
12+
- **OV camera settings** - Apply brightness, contrast, saturation, white balance, exposure, etc. from preferences
13+
- **Singleton pattern** - Classmethod delegation: `CameraManager.add_camera(...)`, `CameraManager.get_cameras()`
14+
- **Hardware-agnostic** - Apps use the same API across all platforms
15+
16+
## Quick Start
17+
18+
### Registering a Camera
19+
20+
Register cameras once at startup in your board init file:
21+
22+
```python
23+
from mpos import CameraManager
24+
25+
# ESP32 with OV5640
26+
CameraManager.add_camera(CameraManager.Camera(
27+
lens_facing=CameraManager.CameraCharacteristics.LENS_FACING_BACK,
28+
name="OV5640",
29+
vendor="OmniVision",
30+
init=my_ov5640_init_function,
31+
deinit=my_ov5640_deinit_function,
32+
capture=my_ov5640_capture_function,
33+
apply_settings=my_ov5640_apply_settings,
34+
rotation_degrees=90,
35+
))
36+
```
37+
38+
### Using Cameras in Apps
39+
40+
```python
41+
from mpos import Activity, CameraManager
42+
43+
class MyCameraActivity(Activity):
44+
def onCreate(self):
45+
if not CameraManager.has_camera():
46+
print("No camera available")
47+
return
48+
49+
self.cam = CameraManager.get_cameras()[0]
50+
self.cam_obj = self.cam.init(320, 240, "RGB565")
51+
52+
def take_photo(self):
53+
image_data = self.cam.capture(self.cam_obj)
54+
# … process image_data …
55+
56+
def onDestroy(self):
57+
if self.cam_obj:
58+
self.cam.deinit(self.cam_obj)
59+
```
60+
61+
### Checking Availability
62+
63+
```python
64+
from mpos import CameraManager
65+
66+
if CameraManager.has_camera():
67+
print(CameraManager.get_camera_count(), "camera(s) available")
68+
else:
69+
print("No camera on this device")
70+
```
71+
72+
## Desktop / V4L2
73+
74+
On Linux desktop builds, the board init file registers a V4L2 camera:
75+
76+
```python
77+
CameraManager.add_camera(CameraManager.Camera(
78+
lens_facing=CameraManager.CameraCharacteristics.LENS_FACING_BACK,
79+
name="V4L2 Camera",
80+
vendor="Linux",
81+
init=cam_init,
82+
deinit=cam_deinit,
83+
capture=cam_capture,
84+
apply_settings=cam_apply_settings,
85+
))
86+
```
87+
88+
## Applying OV Camera Settings
89+
90+
The static helper `ov_apply_camera_settings` reads from a `SharedPreferences` object and applies all supported settings to an OV series camera:
91+
92+
```python
93+
from mpos import CameraManager
94+
from mpos import SharedPreferences
95+
96+
prefs = SharedPreferences("com.micropythonos.camera")
97+
prefs.edit()
98+
.put_int("brightness", 0)
99+
.put_int("contrast", 1)
100+
.put_int("saturation", 0)
101+
.put_bool("hmirror", False)
102+
.put_bool("vflip", False)
103+
.put_bool("whitebal", True)
104+
.put_int("wb_mode", 0)
105+
.apply()
106+
107+
# After init:
108+
CameraManager.ov_apply_camera_settings(cam_obj, prefs)
109+
```
110+
111+
### Supported Settings
112+
113+
| Preference key | Type | Description |
114+
|----------------|------|-------------|
115+
| `brightness` | `int` | -2 to 2 |
116+
| `contrast` | `int` | -2 to 2 |
117+
| `saturation` | `int` | -2 to 2 |
118+
| `hmirror` | `bool` | Horizontal mirror |
119+
| `vflip` | `bool` | Vertical flip |
120+
| `special_effect` | `int` | Effect index |
121+
| `exposure_ctrl` | `bool` | Auto exposure control master switch |
122+
| `aec_value` | `int` | Manual exposure value |
123+
| `ae_level` | `int` | Auto exposure level |
124+
| `aec2` | `bool` | AEC2 mode |
125+
| `gain_ctrl` | `bool` | Auto gain control master switch |
126+
| `agc_gain` | `int` | Manual gain value |
127+
| `gainceiling` | `int` | Gain ceiling |
128+
| `whitebal` | `bool` | Auto white balance master switch |
129+
| `wb_mode` | `int` | White balance mode |
130+
| `awb_gain` | `bool` | AWB gain |
131+
| `sharpness` | `int` | Sharpness (OV5640+) |
132+
| `denoise` | `int` | Denoise level (OV5640+) |
133+
| `colorbar` | `bool` | Color bar test pattern |
134+
| `dcw` | `bool` | Digital crop window |
135+
| `bpc` | `bool` | Black pixel correction |
136+
| `wpc` | `bool` | White pixel correction |
137+
| `raw_gma` | `bool` | Raw gamma correction |
138+
| `lenc` | `bool` | Lens correction |
139+
140+
## Resolution Mapping
141+
142+
Map pixel dimensions to ESP32 `FrameSize` enum values:
143+
144+
```python
145+
from mpos import CameraManager
146+
147+
framesize = CameraManager.resolution_to_framesize(320, 240)
148+
# Returns FrameSize.QVGA
149+
```
150+
151+
Supported resolutions: `(96,96)` through `(1920,1080)`. Falls back to `R240X240` for unknown sizes. Returns `None` if the `camera` module is unavailable (e.g., desktop builds).
152+
153+
## API Reference
154+
155+
### Camera Class
156+
157+
Represents a camera device. Created via `CameraManager.Camera(...)`.
158+
159+
#### `Camera(lens_facing, name=None, vendor=None, version=None, init=None, deinit=None, capture=None, apply_settings=None, rotation_degrees=0)`
160+
161+
- **Parameters:**
162+
- `lens_facing``CameraCharacteristics.LENS_FACING_BACK`, `_FRONT`, or `_EXTERNAL`
163+
- `name` — Human-readable name (e.g., `"OV5640"`)
164+
- `vendor` — Manufacturer name
165+
- `version` — Driver version (default `1`)
166+
- `init``(width, height, colormode) -> camera_object`
167+
- `deinit``(camera_object) -> None`
168+
- `capture``(camera_object, colormode=None) -> image_data`
169+
- `apply_settings``(camera_object, prefs) -> None`
170+
- `rotation_degrees` — Clockwise rotation of the camera sensor
171+
172+
#### `camera.init(width, height, colormode)`
173+
174+
Initialize the camera hardware. Delegates to the registered `init` function.
175+
176+
- **Returns:** Camera object (hardware-specific handle)
177+
178+
#### `camera.deinit(cam_obj=None)`
179+
180+
Release camera hardware. Delegates to the registered `deinit` function.
181+
182+
#### `camera.capture(cam_obj, colormode=None)`
183+
184+
Capture a frame. Delegates to the registered `capture` function.
185+
186+
- **Returns:** Image data bytes
187+
188+
#### `camera.apply_settings(cam_obj, prefs)`
189+
190+
Apply settings from a `SharedPreferences` object. Delegates to the registered `apply_settings` function.
191+
192+
#### `camera.get_rotation_degrees()`
193+
194+
Returns `rotation_degrees` set at construction time.
195+
196+
### CameraCharacteristics
197+
198+
Constants matching Android Camera2 API:
199+
200+
- `LENS_FACING_BACK = 0` — Back-facing camera (primary)
201+
- `LENS_FACING_FRONT = 1` — Front-facing camera (selfie)
202+
- `LENS_FACING_EXTERNAL = 2` — External USB camera
203+
204+
### CameraManager Class
205+
206+
Singleton with classmethod delegation. All methods below are callable as classmethods (`CameraManager.get_cameras()`, etc.).
207+
208+
#### `CameraManager.init()`
209+
210+
Initialize CameraManager. Called automatically on module import.
211+
212+
- **Returns:** `True`
213+
214+
#### `CameraManager.is_available()`
215+
216+
Check if CameraManager is initialized.
217+
218+
- **Returns:** `bool`
219+
220+
#### `CameraManager.add_camera(camera)`
221+
222+
Register a `Camera` object.
223+
224+
- **Returns:** `bool`
225+
226+
#### `CameraManager.get_cameras()`
227+
228+
List all registered cameras.
229+
230+
- **Returns:** `list` of `Camera` objects (copy)
231+
232+
#### `CameraManager.get_camera_by_facing(lens_facing)`
233+
234+
Find first camera with the specified lens facing.
235+
236+
- **Returns:** `Camera` or `None`
237+
238+
#### `CameraManager.has_camera()`
239+
240+
Check if any camera is registered.
241+
242+
- **Returns:** `bool`
243+
244+
#### `CameraManager.get_camera_count()`
245+
246+
Number of registered cameras.
247+
248+
- **Returns:** `int`
249+
250+
#### `CameraManager.resolution_to_framesize(width, height)` *(static)*
251+
252+
Map pixel dimensions to ESP32 `FrameSize` enum.
253+
254+
- **Returns:** `FrameSize` enum value, or `None` if `camera` module unavailable
255+
256+
#### `CameraManager.ov_apply_camera_settings(cam, prefs)` *(static)*
257+
258+
Apply OV camera settings from a `SharedPreferences` object. Safe to call on non-OV cameras — unsupported settings are silently skipped.
259+
260+
- **Parameters:**
261+
- `cam` — Camera object returned by `camera.init()`
262+
- `prefs``SharedPreferences` instance
263+
264+
## See Also
265+
266+
- [Creating Apps](../apps/creating-apps.md)
267+
- [SharedPreferences](preferences.md)
268+
- [DeviceInfo](device-info.md)`FeatureDetector.has_camera()`
269+
- [BuildInfo](build-info.md)`"camera"` feature flag

mkdocs.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,7 @@ nav:
5757
- AudioManager: frameworks/audiomanager.md
5858
- BatteryManager: frameworks/battery-manager.md
5959
- BuildInfo: frameworks/build-info.md
60+
- CameraManager: frameworks/camera-manager.md
6061
- ConnectivityManager: frameworks/connectivity-manager.md
6162
- DeviceInfo: frameworks/device-info.md
6263
- DisplayMetrics: frameworks/display-metrics.md

0 commit comments

Comments
 (0)