camtest: add webcam support

This commit is contained in:
Thomas Farstrike
2025-05-13 16:12:21 +02:00
parent 35303d3a6b
commit fa295e7f57
3 changed files with 46 additions and 16 deletions
+5 -1
View File
@@ -107,7 +107,11 @@ Building for desktop
====================
Building to run as an app on the Linux desktop or MacOS (untested) is supported.
To do so, make sure you have the necessary dependencies (see https://github.com/lvgl-micropython/) and then run:
To do so, make sure you have the necessary dependencies:
- see https://github.com/lvgl-micropython/
- sudo apt install libv4l-dev # for webcam.c
...and then run:
```
~/sources/PiggyOS/scripts/build_lvgl_micropython.sh unix
+23 -3
View File
@@ -1,4 +1,3 @@
//#include <Python.h>
#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
@@ -17,8 +16,8 @@
// Default webcam device
#define VIDEO_DEVICE "/dev/video0"
#define WIDTH 640
#define HEIGHT 480
#define WIDTH 240
#define HEIGHT 240
// Structure to hold webcam state
typedef struct {
@@ -34,6 +33,27 @@ static void yuyv_to_grayscale(uint8_t *src, uint8_t *dst, size_t width, size_t h
}
}
// Resize 640x480 grayscale to 240x240
static void resize_640x480_to_240x240(uint8_t *src, uint8_t *dst) {
const int src_width = 640;
const int src_height = 480;
const int dst_width = 240;
const int dst_height = 240;
// Scaling factors
float x_ratio = (float)src_width / dst_width;
float y_ratio = (float)src_height / dst_height;
for (int y = 0; y < dst_height; y++) {
for (int x = 0; x < dst_width; x++) {
// Nearest-neighbor interpolation
int src_x = (int)(x * x_ratio);
int src_y = (int)(y * y_ratio);
dst[y * dst_width + x] = src[src_y * src_width + src_x];
}
}
}
// Function to capture a grayscale image
static mp_obj_t webcam_capture_grayscale(void) {
webcam_t cam = { .fd = -1, .buffer = NULL, .buffer_length = 0 };
@@ -12,6 +12,7 @@ current_cam_buffer = None
image_dsc = None
image = None
qr_label = None
use_webcam = False
def print_qr_buffer(buffer):
@@ -92,12 +93,12 @@ def qr_button_click(e):
def try_capture():
global current_cam_buffer, image_dsc, image
if cam.frame_available():
# Get new memoryview from camera
global current_cam_buffer, image_dsc, image, use_webcam
if use_webcam:
new_cam_buffer = webcam.capture_grayscale()
elif cam.frame_available():
new_cam_buffer = cam.capture() # Returns memoryview
# Verify buffer size
#if len(new_cam_buffer) != width * height * 2:
if len(new_cam_buffer):
# print("Invalid buffer size:", len(new_cam_buffer))
# cam.free_buffer()
# return
@@ -107,12 +108,11 @@ def try_capture():
image.set_src(image_dsc)
#image.invalidate() #does not work
# Free the previous buffer (if any) after setting new data
if current_cam_buffer is not None:
if current_cam_buffer is not None and not use_webcam:
cam.free_buffer() # Free the old buffer
current_cam_buffer = new_cam_buffer # Store new buffer reference
def build_ui():
global image, image_dsc,qr_label
cont = lv.obj(appscreen)
@@ -195,16 +195,22 @@ def init_cam():
cam = init_cam()
if not cam:
print("init cam failed, retrying...")
time.sleep(5)
cam = init_cam()
print("init cam failed, retrying with webcam...")
try:
import webcam
current_cam_buffer = webcam.capture_grayscale()
use_webcam = True
except Exception as e:
print(f"camtest.py: webcam exception: {e}")
if cam:
if cam or use_webcam:
build_ui()
while appscreen == lv.screen_active() and keepgoing is True:
try_capture()
time.sleep_ms(100) # Allow for the MicroPython REPL to still work. Reducing it doesn't seem to affect the on-display FPS.
print("App backgrounded, deinitializing camera...")
cam.deinit()
show_launcher()
else:
print("No camera found, exiting...")
show_launcher()