Tidy post refactor of cameras

This commit is contained in:
Julian Stirling 2025-05-22 09:13:42 +01:00
parent 4368dc3d90
commit 0e3f4305b5
7 changed files with 22 additions and 46 deletions

View file

@ -24,7 +24,6 @@ from labthings_fastapi.dependencies.blocking_portal import BlockingPortal
from labthings_fastapi.decorators import thing_action, thing_property
from labthings_fastapi.dependencies.metadata import GetThingStates
from labthings_fastapi.types.numpy import NDArray
from labthings_fastapi.dependencies.thing import direct_thing_client_dependency
from labthings_fastapi.dependencies.invocation import InvocationLogger
from .camera import RawCameraDependency as Camera

View file

@ -7,11 +7,12 @@ See repository root for licensing information.
"""
from __future__ import annotations
import logging
from typing import Literal, Optional, Tuple
import json
from pydantic import RootModel
from PIL import Image
import piexif
from labthings_fastapi.thing import Thing
from labthings_fastapi.decorators import thing_action, thing_property

View file

@ -19,7 +19,6 @@ import piexif
from labthings_fastapi.utilities import get_blocking_portal
from labthings_fastapi.decorators import thing_action, thing_property
from labthings_fastapi.dependencies.metadata import GetThingStates
from labthings_fastapi.outputs.mjpeg_stream import MJPEGStreamDescriptor
from labthings_fastapi.types.numpy import NDArray
from . import BaseCamera, JPEGBlob

View file

@ -1,7 +1,5 @@
from __future__ import annotations
from dataclasses import dataclass
from datetime import datetime
import io
import json
import logging
import os
@ -12,19 +10,14 @@ from tempfile import TemporaryDirectory
from pydantic import BaseModel, BeforeValidator
from labthings_fastapi.descriptors.property import PropertyDescriptor
from labthings_fastapi.thing import Thing
from labthings_fastapi.decorators import thing_action, thing_property
from labthings_fastapi.outputs.mjpeg_stream import MJPEGStream
from labthings_fastapi.utilities import get_blocking_portal
from labthings_fastapi.types.numpy import NDArray
from labthings_fastapi.dependencies.metadata import GetThingStates
from labthings_fastapi.dependencies.blocking_portal import BlockingPortal
from typing import Annotated, Any, Iterator, Literal, Mapping, Optional, Self
from typing import Annotated, Any, Iterator, Literal, Mapping, Optional
from contextlib import contextmanager
import piexif
from scipy.ndimage import zoom
from scipy.interpolate import interp1d
from PIL import Image
from threading import RLock
import picamera2
from picamera2 import Picamera2
@ -33,7 +26,7 @@ from picamera2.outputs import Output
import numpy as np
from . import picamera_recalibrate_utils as recalibrate_utils
from . import BaseCamera, JPEGBlob, PNGBlob, ArrayModel
from . import BaseCamera, JPEGBlob, ArrayModel
class PicameraControl(PropertyDescriptor):
@ -636,7 +629,9 @@ class StreamingPiCamera2(BaseCamera):
the processed images. It should not affect raw images.
"""
with self.picamera(pause_stream=True) as cam:
L, Cr, Cb = recalibrate_utils.lst_from_camera(cam)
# Suppress lint warning that L, Cr, and Cb are not lowercase, as this is the
# Standard format for these mathematical vars.
L, Cr, Cb = recalibrate_utils.lst_from_camera(cam) # noqa: N806
recalibrate_utils.set_static_lst(self.tuning, L, Cr, Cb)
self.initialise_picamera()

View file

@ -30,6 +30,11 @@ picamera.lens_shading_table = lst
```
"""
# Disable N806 & 803, which checks that all variables and args are lowercase.
# This is due to the number of matrix calculations and colour channel
# calculations that are clearer using the standard R, G, B, or L, Cr, Cb terms.
# ruff: noqa: N806 N803
from __future__ import annotations
import gc
import logging
@ -43,6 +48,9 @@ from picamera2 import Picamera2
import picamera2
LensShadingTables = tuple[np.ndarray, np.ndarray, np.ndarray]
def load_default_tuning(cam: Picamera2) -> dict:
"""Load the default tuning file for the camera
@ -58,12 +66,13 @@ def load_default_tuning(cam: Picamera2) -> dict:
try:
return cam.load_tuning_file(fname)
except RuntimeError:
dir = "/usr/share/libcamera/ipa/raspberrypi" # from picamera2 v0.3.9
# The directory above has been removed from the search path, which I
tuning_dir = "/usr/share/libcamera/ipa/raspberrypi"
# from picamera2 v0.3.9
# The directory above has been removed from the search path seems
# find odd - as that's where the files currently are on a default
# Raspbian image. This may need updating if the files have moved
# in future updates to the system libcamera package
return cam.load_tuning_file(fname, dir=dir)
return cam.load_tuning_file(fname, dir=tuning_dir)
def set_minimum_exposure(camera: Picamera2):
@ -312,9 +321,6 @@ def channels_from_bayer_array(bayer_array: np.ndarray) -> np.ndarray:
return channels
LensShadingTables = tuple[np.ndarray, np.ndarray, np.ndarray]
def get_16x12_grid(chan: np.ndarray, dx: int, dy: int):
"""Compresses channel down to a 16x12 grid - from libcamera
@ -527,8 +533,8 @@ def raw_channels_from_camera(camera: Picamera2) -> LensShadingTables:
# raw_image is a 3D array, with full resolution and 3 colour channels. No
# de-mosaicing has been done, so 2/3 of the values are zero (3/4 for R and B
# channels, 1/2 for green because there's twice as many green pixels).
format = camera.camera_configuration()["raw"]["format"]
print(f"Acquired a raw image in format {format}")
raw_format = camera.camera_configuration()["raw"]["format"]
print(f"Acquired a raw image in format {raw_format}")
return channels_from_bayer_array(raw_image)
@ -540,24 +546,3 @@ def recreate_camera_manager():
del Picamera2._cm
gc.collect()
Picamera2._cm = picamera2.picamera2.CameraManager()
if __name__ == "__main__":
"""This block is untested but has been updated."""
with Picamera2() as cam:
tuning = load_default_tuning(cam)
f = np.ones((12, 16))
set_static_lst(tuning, f, f, f)
set_static_geq(tuning)
with Picamera2(tuning=tuning) as cam:
cam.start_preview()
time.sleep(3)
logging.info("Recalibrating...")
adjust_shutter_and_gain_from_raw(cam)
adjust_white_balance_from_raw(cam)
lst = lst_from_camera(cam)
set_static_lst(tuning, *lst)
logging.info("Done.")
with Picamera2(tuning=tuning) as cam:
cam.start_preview()
time.sleep(2)

View file

@ -22,9 +22,7 @@ from scipy.ndimage import gaussian_filter
from labthings_fastapi.utilities import get_blocking_portal
from labthings_fastapi.decorators import thing_action, thing_property
from labthings_fastapi.dependencies.metadata import GetThingStates
from labthings_fastapi.types.numpy import NDArray
from labthings_fastapi.server import ThingServer
from pydantic import RootModel
from . import BaseCamera, JPEGBlob, ArrayModel
from ..stage import StageProtocol as Stage
@ -33,7 +31,6 @@ from ..stage import StageProtocol as Stage
# higher related to a faster movement
RATIO = 0.2
class SimulatedCamera(BaseCamera):
"""A Thing representing an OpenCV camera"""