Skip to content

Commit bfd3804

Browse files
CameraActivity: make camera-independent
1 parent 52d7fed commit bfd3804

4 files changed

Lines changed: 168 additions & 156 deletions

File tree

internal_filesystem/lib/mpos/board/linux.py

Lines changed: 29 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -126,20 +126,36 @@ def adc_to_voltage(adc_value):
126126

127127
# === CAMERA HARDWARE ===
128128

129-
try:
130-
# Try to initialize webcam to verify it's available
129+
def init_cam(width, height, colormode):
130+
try:
131+
# Try to initialize webcam to verify it's available
132+
import webcam
133+
return webcam.init("/dev/video0", width=width, height=height)
134+
except Exception as e:
135+
print(f"Info: webcam initialization failed, camera will not be available: {e}")
136+
137+
def deinit_cam(cam_obj):
131138
import webcam
132-
test_cam = webcam.init("/dev/video0", width=320, height=240)
133-
if test_cam:
134-
webcam.deinit(test_cam)
135-
from mpos import CameraManager
136-
CameraManager.add_camera(CameraManager.Camera(
137-
lens_facing=CameraManager.CameraCharacteristics.LENS_FACING_FRONT,
138-
name="Video4Linux2 Camera",
139-
vendor="ACME"
140-
))
141-
except Exception as e:
142-
print(f"Info: webcam initialization failed, camera will not be available: {e}")
139+
webcam.deinit(cam_obj)
140+
141+
def capture_cam(cam_obj, colormode):
142+
import webcam
143+
return webcam.capture_frame(cam_obj, "rgb565" if colormode else "grayscale")
144+
145+
def apply_cam_settings(cam_obj, prefs):
146+
print("V4L Camera doesn't support settings for now, skipping...")
147+
148+
from mpos import CameraManager
149+
CameraManager.add_camera(CameraManager.Camera(
150+
lens_facing=CameraManager.CameraCharacteristics.LENS_FACING_FRONT,
151+
name="Video4Linux2 Camera",
152+
vendor="ACME",
153+
init=init_cam,
154+
deinit=deinit_cam,
155+
capture=capture_cam,
156+
apply_settings=apply_cam_settings
157+
))
158+
143159

144160
print("linux.py finished")
145161

internal_filesystem/lib/mpos/board/matouch_esp32_s3_2_8.py

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -109,6 +109,8 @@ def io0_interrupt_handler(pin):
109109
# LightsManager will not be initialized (functions will return False)
110110

111111
# === CAMERA HARDWARE ===
112+
from mpos import CameraManager
113+
112114
def init_cam(width, height, colormode):
113115
try:
114116
from camera import Camera, GrabMode, PixelFormat, FrameSize, GainCeiling
@@ -203,7 +205,11 @@ def deinit_cam(cam):
203205
except Exception as e:
204206
print(f"Indev enable got exception: {e}")
205207

206-
from mpos import CameraManager
208+
def capture_cam(cam_obj, colormode):
209+
return cam_obj.capture()
210+
211+
def apply_cam_settings(cam_obj, prefs):
212+
return CameraManager.ov_apply_camera_settings(cam_obj, prefs)
207213

208214
# MaTouch ESP32-S3 has OV3660 camera (3MP, up to 2048x1536)
209215
# Camera pins are available but initialization is handled by the camera driver
@@ -213,6 +219,7 @@ def deinit_cam(cam):
213219
vendor="OmniVision",
214220
init=init_cam,
215221
deinit=deinit_cam,
222+
capture=capture_cam
216223
))
217224

218225
print("matouch_esp32_s3_2_8.py finished")

internal_filesystem/lib/mpos/camera_manager.py

Lines changed: 122 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ class Camera:
3737
Represents a camera device with its characteristics.
3838
"""
3939

40-
def __init__(self, lens_facing, name=None, vendor=None, version=None, init=None, deinit=None):
40+
def __init__(self, lens_facing, name=None, vendor=None, version=None, init=None, deinit=None, capture=None, apply_settings=None):
4141
"""Initialize camera metadata.
4242
4343
Args:
@@ -52,6 +52,8 @@ def __init__(self, lens_facing, name=None, vendor=None, version=None, init=None,
5252
self.version = version or 1
5353
self.init_function = init
5454
self.deinit_function = deinit
55+
self.capture_function = capture
56+
self.apply_settings_function = apply_settings
5557

5658
def __repr__(self):
5759
facing_names = {
@@ -70,6 +72,14 @@ def deinit(self, cam_obj=None):
7072
if self.deinit_function:
7173
return self.deinit_function(cam_obj)
7274

75+
def capture(self, cam_obj, colormode=None):
76+
if self.capture_function:
77+
return self.capture_function(cam_obj, colormode)
78+
79+
def apply_settings(self, cam_obj, prefs):
80+
if self.apply_settings_function:
81+
return self.apply_settings_function(cam_obj, prefs)
82+
7383
class CameraManager:
7484
"""
7585
Centralized camera device management service.
@@ -237,6 +247,117 @@ def resolution_to_framesize(width, height):
237247

238248
return resolution_map.get((width, height), FrameSize.R240X240)
239249

250+
@staticmethod
251+
def ov_apply_camera_settings(self, cam, prefs):
252+
if not cam or not prefs:
253+
print("ov_apply_camera_settings: Skipping because invalid prefs or cam object")
254+
return
255+
256+
try:
257+
# Basic image adjustments
258+
brightness = prefs.get_int("brightness")
259+
cam.set_brightness(brightness)
260+
261+
contrast = prefs.get_int("contrast")
262+
cam.set_contrast(contrast)
263+
264+
saturation = prefs.get_int("saturation")
265+
cam.set_saturation(saturation)
266+
267+
# Orientation
268+
hmirror = prefs.get_bool("hmirror")
269+
cam.set_hmirror(hmirror)
270+
271+
vflip = prefs.get_bool("vflip")
272+
cam.set_vflip(vflip)
273+
274+
# Special effect
275+
special_effect = prefs.get_int("special_effect")
276+
cam.set_special_effect(special_effect)
277+
278+
# Exposure control (apply master switch first, then manual value)
279+
exposure_ctrl = prefs.get_bool("exposure_ctrl")
280+
cam.set_exposure_ctrl(exposure_ctrl)
281+
282+
if not exposure_ctrl:
283+
aec_value = prefs.get_int("aec_value")
284+
cam.set_aec_value(aec_value)
285+
286+
# Mode-specific default comes from constructor
287+
ae_level = prefs.get_int("ae_level")
288+
cam.set_ae_level(ae_level)
289+
290+
aec2 = prefs.get_bool("aec2")
291+
cam.set_aec2(aec2)
292+
293+
# Gain control (apply master switch first, then manual value)
294+
gain_ctrl = prefs.get_bool("gain_ctrl")
295+
cam.set_gain_ctrl(gain_ctrl)
296+
297+
if not gain_ctrl:
298+
agc_gain = prefs.get_int("agc_gain")
299+
cam.set_agc_gain(agc_gain)
300+
301+
gainceiling = prefs.get_int("gainceiling")
302+
cam.set_gainceiling(gainceiling)
303+
304+
# White balance (apply master switch first, then mode)
305+
whitebal = prefs.get_bool("whitebal")
306+
cam.set_whitebal(whitebal)
307+
308+
if not whitebal:
309+
wb_mode = prefs.get_int("wb_mode")
310+
cam.set_wb_mode(wb_mode)
311+
312+
awb_gain = prefs.get_bool("awb_gain")
313+
cam.set_awb_gain(awb_gain)
314+
315+
# Sensor-specific settings (try/except for unsupported sensors)
316+
try:
317+
sharpness = prefs.get_int("sharpness")
318+
cam.set_sharpness(sharpness)
319+
except:
320+
pass # Not supported on OV2640?
321+
322+
try:
323+
denoise = prefs.get_int("denoise")
324+
cam.set_denoise(denoise)
325+
except:
326+
pass # Not supported on OV2640?
327+
328+
# Advanced corrections
329+
colorbar = prefs.get_bool("colorbar")
330+
cam.set_colorbar(colorbar)
331+
332+
dcw = prefs.get_bool("dcw")
333+
cam.set_dcw(dcw)
334+
335+
bpc = prefs.get_bool("bpc")
336+
cam.set_bpc(bpc)
337+
338+
wpc = prefs.get_bool("wpc")
339+
cam.set_wpc(wpc)
340+
341+
# Mode-specific default comes from constructor
342+
raw_gma = prefs.get_bool("raw_gma")
343+
print(f"applying raw_gma: {raw_gma}")
344+
cam.set_raw_gma(raw_gma)
345+
346+
lenc = prefs.get_bool("lenc")
347+
cam.set_lenc(lenc)
348+
349+
# JPEG quality (only relevant for JPEG format)
350+
#try:
351+
# quality = prefs.get_int("quality", 85)
352+
# cam.set_quality(quality)
353+
#except:
354+
# pass # Not in JPEG mode
355+
356+
print("Camera settings applied successfully")
357+
358+
except Exception as e:
359+
print(f"Error applying camera settings: {e}")
360+
240361

241362
# ============================================================================
242363
# Class method delegation (at module level)

0 commit comments

Comments
 (0)