picamera2 icon indicating copy to clipboard operation
picamera2 copied to clipboard

[BUG] .capture_array() halving framerate

Open EPstudios opened this issue 1 year ago • 3 comments

Describe the bug When calling .capture_array() the frame rate drops in half according to details in .capture_metadata()['SensorTimestamp'] Have added timers to check .capture_array() is blocking the script thus dropping frames and all seems fine. Tried various resolutions (down to 320 x 240) and the issue persists. Strangely if i set the framerate (with to_array = True) to 25 it will give me 12.5, but if i set the framerate to 50 it will give me 25.

Could well be user error, but i cant figure it out. Any help would be appreciated.

To Reproduce

#changing to_array to True will cause the issue

from picamera2 import Picamera2
import time
import sys
import os

last_timestamp = 0

to_array = False

def frame_time(cam):
    global last_timestamp
    picam2 = cam
    timestamp = picam2.capture_metadata()['SensorTimestamp']
    frameTime = (timestamp - last_timestamp) / 1000000
    last_timestamp = timestamp
    return frameTime

def main():
    picam2 = Picamera2()
    print("\n Sensor modes...." )
    print(picam2.sensor_modes)

    config = picam2.create_video_configuration(
    main={"size": (1280, 720), "format": "RGB888"}, 
    controls={"FrameRate": 50},
    buffer_count=4
    )
    picam2.configure(config)
    print("\n Config....")
    print(config)

    picam2.start()

    print("\n Meta data....")
    metadata = picam2.capture_metadata()
    print(metadata,"\n")

    while True:
        #1st
        a_time = time.time()
        this_frame_time = frame_time(picam2)
        #2nd
        b_time = time.time()
        if to_array:
            img = picam2.capture_array("main")
            c_time = time.time()
            print("Res:", img.shape)
            print("Fps:",round(1000/this_frame_time, 2),"1st:",b_time - a_time, "2nd:",c_time-b_time, "Total:", c_time-a_time)
        
        
        else: 
            c_time = time.time()
            print("Fps:",round(1000/this_frame_time, 2),"1st:",b_time - a_time, "2nd:",c_time-b_time, "Total:", c_time-a_time)
            
            
if __name__ == '__main__':
    try:
        main()
    except KeyboardInterrupt:
        print('Interrupted')
        try:
            sys.exit(130)
        except SystemExit:
            os._exit(130)

Console Output, Screenshots

Not sure why .sensor_modes is returning configuring streams: on two separate occasions with differing values?

INFO Camera camera_manager.cpp:297 libcamera v0.0.5+83-bde9b04f
INFO RPI vc4.cpp:437 Registered camera /base/soc/i2c0mux/i2c@1/imx296@1a to Unicam device /dev/media4 and ISP device /dev/media1
INFO RPI pipeline_base.cpp:1101 Using configuration file '/usr/share/libcamera/pipeline/rpi/vc4/rpi_apps.yaml'

 Sensor modes....
 INFO Camera camera.cpp:1033 configuring streams: (0) 640x480-XBGR8888 (1) 1456x1088-SBGGR10_CSI2P
INFO RPI vc4.cpp:565 Sensor: /base/soc/i2c0mux/i2c@1/imx296@1a - Selected sensor format: 1456x1088-SBGGR10_1X10 - Selected unicam format: 1456x1088-pBAA
[{'format': SRGGB10_CSI2P, 'unpacked': 'SRGGB10', 'bit_depth': 10, 'size': (1456, 1088), 'fps': 60.38, 'crop_limits': (0, 0, 1456, 1088), 'exposure_limits': (29, None)}]
INFO Camera camera.cpp:1033 configuring streams: (0) 1280x720-RGB888 (1) 1456x1088-SBGGR10_CSI2P
INFO RPI vc4.cpp:565 Sensor: /base/soc/i2c0mux/i2c@1/imx296@1a - Selected sensor format: 1456x1088-SBGGR10_1X10 - Selected unicam format: 1456x1088-pBAA

 Config....
{'use_case': 'video', 'transform': <libcamera.Transform 'identity'>, 'colour_space': <libcamera.ColorSpace 'Rec709'>, 'buffer_count': 4, 'queue': True, 'main': {'format': 'RGB888', 
'size': (1280, 720), 'stride': 3840, 'framesize': 2764800}, 'lores': None, 'raw': {'format': 'SBGGR10_CSI2P', 'size': (1456, 1088), 'stride': 1824, 'framesize': 1984512}, 
'controls': {'NoiseReductionMode': <NoiseReductionModeEnum.Fast: 1>, 'FrameDurationLimits': (33333, 33333), 'FrameRate': 50}, 'display': 'main', 'encode': 'main'}

 Meta data....
{'ScalerCrop': (0, 135, 1456, 819), 'SensorBlackLevels': (3840, 3840, 3840, 3840), 'ColourTemperature': 5189, 'DigitalGain': 1.2002097368240356, 
'ColourGains': (3.1467363834381104, 1.7512365579605103), 'AeLocked': False, 'Lux': 137.99920654296875, 'FrameDuration': 20014, 
'ColourCorrectionMatrix': (1.8978495597839355, -0.7924068570137024, -0.11689109355211258, -0.23124268651008606, 1.5891221761703491, -0.3659903407096863, 0.08053405582904816, -0.6482157111167908, 1.562030553817749), 
'SensorTimestamp': 41658557837000, 'AnalogueGain': 1.4288939237594604, 'FocusFoM': 1333, 'ExposureTime': 19940} 

Example print out with to_array set to False Fps: 50.0 1st: 0.022350549697875977 2nd: 9.5367431640625e-07 Total: 0.022351503372192383

Example print out with to_arrayset to True (also confirming array size)

Res: (720, 1280, 3)
Fps: 25.0 1st: 0.011664390563964844 2nd: 0.027348756790161133 Total: 0.03901314735412598

Hardware : RPI 4 with PI Global shutter camera

Additional context bullseye 64 bit lite (running headless) Python 3.9.2 picamera2 0.3.12

EPstudios avatar Feb 09 '24 12:02 EPstudios