From 06be8c83ead54f11f7115576cd47258676422369 Mon Sep 17 00:00:00 2001 From: Jens Ahrensfeld Date: Mon, 15 Jul 2024 17:27:24 +0200 Subject: [PATCH] - read metadata in callback - clamp shutter speed to frame duration minimum --- ocv_rpicam.py | 101 ++++++++++++++++++++++++++++++-------------------- settings.json | 4 +- 2 files changed, 63 insertions(+), 42 deletions(-) diff --git a/ocv_rpicam.py b/ocv_rpicam.py index 79baf8a..14d8146 100755 --- a/ocv_rpicam.py +++ b/ocv_rpicam.py @@ -1,6 +1,7 @@ #!/usr/bin/env python3 + from typing import Union, overload -from picamera2 import Picamera2, MappedArray +from picamera2 import Picamera2, MappedArray, Metadata from pprint import pprint import json import cv2 @@ -38,11 +39,10 @@ picam2 = Picamera2() pprint(picam2.sensor_modes) settings = {'NoiseReductionMode': 0, 'AeExposureMode': 0, 'ExposureTime': 10000, 'AnalogueGain': 1, 'FrameRate': picam2.sensor_modes[0]['fps']} caps = {"FrameRate": (1, picam2.sensor_modes[0]['fps'], None)} -fps = 0 def load_settings(): - _result = None + _result = {} try: with open("settings.json", "r") as fp: _result = json.load(fp) @@ -76,24 +76,39 @@ def set_value(item: str, value): def get_value(item: str): return picam2.camera_controls[item] - + +fps_ist = 0 +fps_soll = 0 + def process(request): - global fps timestamp = time.strftime("%Y-%m-%d %X") + # read metadata from request + metadata = Metadata(request.get_metadata()) + + # Clamp our shutter value to minimum of FrameDuration + caps["ExposureTime"] = (caps["ExposureTime"][0], metadata.FrameDuration) + with MappedArray(request, "main") as m: # Display timestamp on frame cv2.putText(m.array, timestamp, (0, 30), cv2.FONT_HERSHEY_SIMPLEX, 1, (0, 255, 0), 2) + if metadata is not None: + # Display exposure time + cv2.putText(m.array, f"ExposureTime : {metadata.ExposureTime:.1f}/{shutter:.1f}", (20, m.array.shape[0] - 80), cv2.FONT_HERSHEY_SIMPLEX, 1, (0, 240, 0), 2) + + # Display frame time + cv2.putText(m.array, f"FrameDuration : {metadata.FrameDuration:.1f}", (20, m.array.shape[0] - 50), cv2.FONT_HERSHEY_SIMPLEX, 1, (0, 240, 0), 2) + # Display FPS on frame - cv2.putText(m.array, "FPS : " + str(int(fps)), (20, m.array.shape[0] - 20), cv2.FONT_HERSHEY_SIMPLEX, 1, (0, 240, 0), 2) + cv2.putText(m.array, f"Frame rate : {fps_ist:.1f}/{fps_soll:.1f}", (20, m.array.shape[0] - 20), cv2.FONT_HERSHEY_SIMPLEX, 1, (0, 240, 0), 2) if __name__ == '__main__': for item in items: try: - caps[item] = picam2.camera_controls[item] + caps[item] = (picam2.camera_controls[item][0], picam2.camera_controls[item][1]) except KeyError: print(f"{item}: Not implemented") @@ -102,25 +117,32 @@ if __name__ == '__main__': camera_config = picam2.create_preview_configuration({'format': 'XRGB8888', 'size': (800, 600)}) picam2.configure(camera_config) - + # Load and apply our settings settings |= load_settings() - shutter = settings['ExposureTime'] - gain = settings['AnalogueGain'] - fps = settings['FrameRate'] apply_settings(settings) + # Init vars + shutter = settings['ExposureTime'] + gain = settings['AnalogueGain'] + fps_soll = settings['FrameRate'] + + # Print status pprint(f"Capabilities: {caps}") pprint(f"Settings: {settings}") pprint(f"Camera config: {picam2.camera_configuration()}") - # Start + # Register OCV processing callback picam2.pre_callback = process + + # Start picam2.start() while True: + # Start timer timer = cv2.getTickCount() + # Capture frame frame = picam2.capture_array("main") # Process the frame using OpenCV operations @@ -132,63 +154,62 @@ if __name__ == '__main__': break elif key == ord('w'): shutter -= 1000 - shutter = set_value('ExposureTime', shutter) print(f"Shutter: {shutter}") elif key == ord('s'): shutter -= 100 - shutter = set_value('ExposureTime', shutter) print(f"Shutter: {shutter}") elif key == ord('x'): shutter -= 1 - shutter = set_value('ExposureTime', shutter) print(f"Shutter: {shutter}") elif key == ord('e'): shutter += 1000 - shutter = set_value('ExposureTime', shutter) print(f"Shutter: {shutter}") elif key == ord('d'): shutter += 100 - shutter = set_value('ExposureTime', shutter) print(f"Shutter: {shutter}") elif key == ord('c'): shutter += 1 - shutter = set_value('ExposureTime', shutter) print(f"Shutter: {shutter}") elif key == ord('h'): gain -= 1 - gain = set_value('AnalogueGain', gain) print(f"Gain: {gain}") elif key == ord('j'): gain += 1 - gain = set_value('AnalogueGain', gain) print(f"Gain: {gain}") elif key == ord('r'): - fps -= 1 - fps = set_value('FrameRate', fps) - print(f"FPS: {fps}") + fps_soll -= 1 + print(f"FPS: {fps_soll}") elif key == ord('f'): - fps -= 0.1 - fps = set_value('FrameRate', fps) - print(f"FPS: {fps}") + fps_soll -= 0.1 + print(f"FPS: {fps_soll}") elif key == ord('v'): - fps -= 0.01 - fps = set_value('FrameRate', fps) - print(f"FPS: {fps}") + fps_soll -= 0.01 + print(f"FPS: {fps_soll}") elif key == ord('t'): - fps += 1 - fps = set_value('FrameRate', fps) - print(f"FPS: {fps}") + fps_soll += 1 + print(f"FPS: {fps_soll}") elif key == ord('g'): - fps += 0.1 - fps = set_value('FrameRate', fps) - print(f"FPS: {fps}") + fps_soll += 0.1 + print(f"FPS: {fps_soll}") elif key == ord('b'): - fps += 0.01 - fps = set_value('FrameRate', fps) - print(f"FPS: {fps}") + fps_soll += 0.01 + print(f"FPS: {fps_soll}") - # Calculate Frames per second (FPS) - fps = cv2.getTickFrequency() / (cv2.getTickCount() - timer) + # Update control settings and keep vars within ranges + shutter = set_value('ExposureTime', shutter) + gain = set_value('AnalogueGain', gain) + fps_soll = set_value('FrameRate', fps_soll) + + # Write contrrols to camera + with picam2.controls as controls: + controls.ExposureTime = shutter + controls.AnalogueGain = gain + controls.FrameRate = fps_soll + + # Calculate Frames per second (FPS) + fr = cv2.getTickFrequency() / (cv2.getTickCount() - timer) + alpha = 0.2 + fps_ist = (1-alpha)*fps_ist + alpha*fr # Release the capture and close windows diff --git a/settings.json b/settings.json index 21186ba..6de1cb7 100755 --- a/settings.json +++ b/settings.json @@ -1,7 +1,7 @@ { "NoiseReductionMode": 0, "AeExposureMode": 0, -"ExposureTime": 75030, +"ExposureTime": 10000, "AnalogueGain": 1.0, -"FrameRate": 10.580000000000002 +"FrameRate": 60.38 } \ No newline at end of file