adafruit / circuitpython

CircuitPython - a Python implementation for teaching coding with microcontrollers
https://circuitpython.org
Other
4.12k stars 1.22k forks source link

`espcamera` erroneously fails on low quality - high resolution photos #8398

Open bill88t opened 1 year ago

bill88t commented 1 year ago

CircuitPython version

Adafruit CircuitPython 9.0.0-alpha.1-39-g3032d4e7d5 on 2023-09-13; M5Stack Timer Camera X with ESP32

Code/REPL

import espcamera, board

a = espcamera.Camera(data_pins=board.D, pixel_clock_pin=board.PCLK, vsync_pin=board.VSYNC, href_pin=board.HREF, i2c=board.SSCB_I2C(), external_clock_pin=board.XCLK, external_clock_frequency=20_000_000, powerdown_pin=None, reset_pin=board.RESET, pixel_format=espcamera.PixelFormat.JPEG, frame_size=espcamera.FrameSize.QXGA, jpeg_quality=2, framebuffer_count=1, grab_mode=espcamera.GrabMode.LATEST)

try:
    while True:
        b = a.take(1)
        print(type(b))
        del b
except KeyboardInterrupt:
    pass

Behavior

<class 'memoryview'>
<class 'NoneType'>
<class 'NoneType'>
<class 'NoneType'>
<class 'NoneType'>
<class 'NoneType'>
<class 'NoneType'>

Description

If I cover the lens, this makes the photos really tiny in terms of data and it always succeeds. This leads me to believe lower qualities need more proccessing and lead to failure even if they get a bigger timeout. (I tried giving it 20s, docs state the time is in ms, but it's not, it's actually seconds, I will correct that later)

If I also just raise the quality slowly, the success rate increases. Around 12 it becomes almost 100% regardless of what is in the frame. Sharp contrasts, like 50% of the lens being black and the other 50% staring at my ceiling light make it fail a lot more. If I just set the quality to 55 which is the max, it never fails or lags.

Additional information

ov3660

jepler commented 1 year ago

I found extreme values unreliable which is why I wrote in the documentation:

The exact range of appropriate values depends on the sensor and must be determined empirically.

I recommend making a build that will show esp-idf log messages & seeing if anything useful turns up. Or, try the same jpeg settings in their sample app that builds without circuitpython to see if the failure occurs there too.

There's a very simplisitic calculation of the needed buffer size based on resolution in espcamera:

    if(cam_obj->jpeg_mode){
        cam_obj->recv_size = cam_obj->width * cam_obj->height / 5;
        cam_obj->fb_size = cam_obj->recv_size;

weirdly this doesn't account for a quality value at all, which could be why extremely high values fail. I do not know why extremely low values would fail, though.

bill88t commented 1 year ago

I will be getting more camera boards soon (you will see the PRs), so I plan on logging and comparing different cameras and their settings success rates then.