Is it possible to dynamically set frame sizes using sensor.set_framesize()?

Hello,
I’m working on a project where I need to dynamically change the camera’s frame size based on UART commands and then capture and send images over UART. I want to confirm if my approach to setting frame sizes is even possible. I get the error RuntimeError: Frame size is not supported or is not set when running it. Here’s my code:


import sensor, pyb, time
from machine import UART

# Configuration
pyb.freq(400000000)
GREEN_LED_PIN = 2
BLUE_LED_PIN = 3
uart = UART(3, 115200)
uart.init(115200, bits=8, parity=None, stop=1)
counter = 1
# Initialize Camera
def initialize_camera():
    sensor.reset()  
    sensor.set_pixformat(sensor.RGB565) 
    sensor.skip_frames(time=2000)
   
# Globals
GOOD_IMAGE = 0
resolution_set = False  # Flag to indicate resolution change

def clear_uart_buffer(uart):
    while uart.any():
        uart.read()

# Function to set camera resolution
def set_camera_resolution(mode):
    pyb.LED(BLUE_LED_PIN).on()
    global resolution_set
    initialize_camera()
    if mode == "QVGA":
        sensor.set_framesize(sensor.QVGA)
        capture_image()
    elif mode == "VGA":
        sensor.set_framesize(sensor.VGA)
        capture_image()
    elif mode == "HD":
        sensor.set_framesize(sensor.HD)
        capture_image()
    else:
        print("Invalid mode!")
        return False
    print(f"Camera resolution set to: {mode}")
    resolution_set = True
    pyb.LED(BLUE_LED_PIN).off()
    return True

# Capture an image
def capture_image():
    global counter
    try:
        pyb.LED(GREEN_LED_PIN).on()
        img = sensor.snapshot()
        picture = f"NIR_{counter}.jpg"
        img.save(picture)
        counter += 1  # Increment counter
        with open(picture, "rb") as f:
            image_data = f.read()
            image_size = len(image_data)
            length = str(image_size) + '\n'
            print("image size:", length)
        raw_metadata = f"NIR{counter}S:{image_size}"
        metadata = (raw_metadata + "XXXXXXXXXXXXX" * 13)[:13] + "\n"
        print("Metadata:", metadata.strip())
        uart.write(metadata.encode())
        pyb.delay(100)
        uart.write(image_data)
        print("Image sent")
    except Exception as e:
        print("Error:", e)
    finally:
        pyb.LED(GREEN_LED_PIN).off()


# Parse UART command and handle modes
def parse_command(command):
    if command is None or len(command) < 1:
        print("Invalid or empty command!")
        return
    if 0x31 in command:  # ASCII B
        set_camera_resolution("QVGA")
        print("[DEBUG] Switching to QVGA mode.")
    elif 0x41 in command:  # ASCIIA
        set_camera_resolution("VGA")
        print("[DEBUG] Switching to VGA mode.")
    elif 0x43 in command:  # ASCII C
        set_camera_resolution("HD")
        print("[DEBUG] Switching to HD mode.")
    else:
        print("Unknown mode!")


# Main Loop
while True:
    clear_uart_buffer(uart)
    pyb.LED(BLUE_LED_PIN).on()
    # pyb.delay(3000)
    if uart.any():
        command = uart.read()
        pyb.LED(BLUE_LED_PIN).toggle()
        parse_command(command)
        pyb.delay(1000)
        capture_image()
        pyb.LED(BLUE_LED_PIN).off()
        resolution_set = False

I am trying to initialize the camera using sensor.reset() and sensor.set_pixformat(sensor.RGB565).Use sensor.set_framesize() to set the frame size dynamically based on the command received over UART. The frame size options I am handling are: QVGA (320x240), VGA (640x480) and HD(1280x720). Any guidance or suggestions on my implementation would be helpful. I am doing this on OpenMV H7 plus.

Thank you.

You need to have a frame size set before capturing any images.

Next time you post code please use code blocks so we can read it.

1 Like