Fix camera type issues
This commit is contained in:
parent
9976c5cb84
commit
99eee2e912
5 changed files with 22 additions and 42 deletions
|
|
@ -288,7 +288,7 @@ class StreamingPiCamera2(BaseCamera):
|
|||
"Sharpness": 1,
|
||||
}
|
||||
|
||||
_sensor_modes = None
|
||||
_sensor_modes: Optional[list[SensorMode]] = None
|
||||
|
||||
@lt.property
|
||||
def sensor_modes(self) -> list[SensorMode]:
|
||||
|
|
@ -363,6 +363,9 @@ class StreamingPiCamera2(BaseCamera):
|
|||
camera_num=self._camera_num,
|
||||
tuning=self.tuning,
|
||||
)
|
||||
if self._picamera is None:
|
||||
# Type narrow (error if failure)
|
||||
raise RuntimeError("Failed to start Picamera")
|
||||
if check_sensor_model:
|
||||
hw_sensor_model = self._picamera.camera_properties["Model"]
|
||||
if hw_sensor_model != self._sensor_info.sensor_model:
|
||||
|
|
@ -861,7 +864,7 @@ class StreamingPiCamera2(BaseCamera):
|
|||
]
|
||||
|
||||
@lt.property
|
||||
def lens_shading_tables(self) -> Optional[tf_utils.LensShading]:
|
||||
def lens_shading_tables(self) -> Optional[tf_utils.LensShadingModel]:
|
||||
"""The current lens shading (i.e. flat-field correction).
|
||||
|
||||
Return the current lens shading correction, as three 2D lists each with
|
||||
|
|
@ -874,19 +877,6 @@ class StreamingPiCamera2(BaseCamera):
|
|||
"""
|
||||
return tf_utils.get_lst(self.tuning)
|
||||
|
||||
@lens_shading_tables.setter
|
||||
def _set_lens_shading_tables(self, lst: tf_utils.LensShading) -> None:
|
||||
"""Set the lens shading tables."""
|
||||
with self._streaming_picamera(pause_stream=True):
|
||||
self.tuning = tf_utils.set_lst(
|
||||
self.tuning,
|
||||
luminance=lst.luminance,
|
||||
cr=lst.Cr,
|
||||
cb=lst.Cb,
|
||||
colour_temp=lst.colour_temp,
|
||||
)
|
||||
self._initialise_picamera()
|
||||
|
||||
@lt.action
|
||||
def flat_lens_shading(self) -> None:
|
||||
"""Disable flat-field correction.
|
||||
|
|
|
|||
|
|
@ -51,7 +51,6 @@ import numpy as np
|
|||
import picamera2
|
||||
from picamera2 import Picamera2
|
||||
from pydantic import BaseModel
|
||||
from scipy.ndimage import zoom
|
||||
|
||||
LOGGER = logging.getLogger(__name__)
|
||||
|
||||
|
|
@ -322,18 +321,7 @@ def _get_16x12_grid(chan: np.ndarray, dx: int, dy: int) -> np.ndarray:
|
|||
return np.reshape(np.array(grid), (12, 16))
|
||||
|
||||
|
||||
def _upsample_channels(grids: np.ndarray, shape: tuple[int]) -> np.ndarray:
|
||||
"""Zoom an image in the last two dimensions.
|
||||
|
||||
This is effectively the inverse operation of ``_get_16x12_grid``
|
||||
"""
|
||||
zoom_factors = [
|
||||
1,
|
||||
] + list(np.ceil(np.array(shape) / np.array(grids.shape[1:])))
|
||||
return zoom(grids, zoom_factors, order=1)[:, : shape[0], : shape[1]]
|
||||
|
||||
|
||||
def _downsampled_channels(channels: np.ndarray, blacklevel: int) -> list[np.ndarray]:
|
||||
def _downsampled_channels(channels: np.ndarray, blacklevel: int) -> np.ndarray:
|
||||
"""Generate a downsampled, un-normalised image from which to calculate the LST."""
|
||||
channel_shape = np.array(channels.shape[1:])
|
||||
lst_shape = np.array([12, 16])
|
||||
|
|
@ -398,9 +386,7 @@ def _grids_from_lst(lum: np.ndarray, Cr: np.ndarray, Cb: np.ndarray) -> np.ndarr
|
|||
return np.stack([B, G, G, R], axis=0)
|
||||
|
||||
|
||||
def _raw_channels_from_camera(
|
||||
camera: Picamera2, sensor_info: SensorInfo
|
||||
) -> LensShadingTables:
|
||||
def _raw_channels_from_camera(camera: Picamera2, sensor_info: SensorInfo) -> np.ndarray:
|
||||
"""Acquire a raw image and return a 4xNxM array of the colour channels."""
|
||||
if camera.started:
|
||||
camera.stop_recording()
|
||||
|
|
|
|||
|
|
@ -20,9 +20,12 @@ CALIBRATED_COLOUR_TEMP = 5000
|
|||
DEFAULT_COLOUR_TEMP = 1234
|
||||
|
||||
|
||||
class LensShading(BaseModel):
|
||||
class LensShadingModel(BaseModel):
|
||||
"""A Pydantic model holding the lens shading tables.
|
||||
|
||||
Note this shouldn't be confused with the typehint for LensShadingTables in
|
||||
recalibrate utils which is for the arrays.
|
||||
|
||||
PiCamera needs three numpy arrays for lens shading correction. Each array is
|
||||
(12, 16) in size. The arrays are luminance, red-difference chroma (Cr), and
|
||||
blue-difference chroma (Cb).
|
||||
|
|
@ -165,7 +168,7 @@ def flatten_lst(tuning: dict, keep_luminance: bool = False) -> dict:
|
|||
)
|
||||
|
||||
|
||||
def get_lst(tuning: dict) -> LensShading:
|
||||
def get_lst(tuning: dict) -> LensShadingModel:
|
||||
"""Return the lens shading as a LenSading Base Model."""
|
||||
# Note "alsc" is the Picamera2 term for "Automatic Lens Shading Correction"
|
||||
alsc = find_tuning_algo(tuning, "rpi.alsc")
|
||||
|
|
@ -175,7 +178,7 @@ def get_lst(tuning: dict) -> LensShading:
|
|||
w, h = 16, 12
|
||||
return [lin[w * i : w * (i + 1)] for i in range(h)]
|
||||
|
||||
return LensShading(
|
||||
return LensShadingModel(
|
||||
luminance=reshape_lst(alsc["luminance_lut"]),
|
||||
Cr=reshape_lst(alsc["calibrations_Cr"][0]["table"]),
|
||||
Cb=reshape_lst(alsc["calibrations_Cb"][0]["table"]),
|
||||
|
|
|
|||
|
|
@ -33,7 +33,7 @@ from . import BaseCamera
|
|||
|
||||
LOGGER = logging.getLogger(__name__)
|
||||
|
||||
# The ratio between "motor" steps and pixels
|
||||
# The ratio between "motor" steps and pixels in (x, y, z)
|
||||
# higher related to a faster movement
|
||||
RATIO = (2, 2, 0.2)
|
||||
|
||||
|
|
@ -203,10 +203,11 @@ class SimulatedCamera(BaseCamera):
|
|||
"""
|
||||
canvas_width, canvas_height, _ = self.canvas_shape
|
||||
image_width, image_height, _ = self.shape
|
||||
pos = tuple(x * s for x, s in zip(pos, RATIO, strict=True))
|
||||
# Scale position by RATIO to get position in base image.
|
||||
im_pos = tuple(x * ratio for x, ratio in zip(pos, RATIO, strict=True))
|
||||
top_left = (
|
||||
int(pos[0]) - image_width // 2 + self.sample_limits[0] // 2,
|
||||
int(pos[1]) - image_height // 2 + self.sample_limits[1] // 2,
|
||||
int(im_pos[0]) - image_width // 2 + self.sample_limits[0] // 2,
|
||||
int(im_pos[1]) - image_height // 2 + self.sample_limits[1] // 2,
|
||||
)
|
||||
# Create index list with modulo rather than slicing to handle wrapping at the
|
||||
# canvas edge.
|
||||
|
|
@ -217,7 +218,7 @@ class SimulatedCamera(BaseCamera):
|
|||
# Use npx to make each 1d index list 3D
|
||||
focused_image = canvas[np.ix_(x_indices, y_indices, z_indices)]
|
||||
|
||||
image = fast_pil_blur(focused_image, sigma=np.abs(pos[2]) / 5)
|
||||
image = fast_pil_blur(focused_image, sigma=np.abs(im_pos[2]) / 5)
|
||||
|
||||
if image.shape != self.shape:
|
||||
raise ValueError(
|
||||
|
|
@ -251,7 +252,7 @@ class SimulatedCamera(BaseCamera):
|
|||
_traceback: Optional[TracebackType],
|
||||
) -> None:
|
||||
"""Close the capture thread when the Thing context manager is closed."""
|
||||
if self.stream_active:
|
||||
if self._capture_thread is not None and self._capture_thread.is_alive():
|
||||
self._capture_enabled = False
|
||||
self._capture_thread.join()
|
||||
|
||||
|
|
@ -300,7 +301,7 @@ class SimulatedCamera(BaseCamera):
|
|||
try:
|
||||
frame = self.generate_frame()
|
||||
self.mjpeg_stream.add_frame(_frame2bytes(frame))
|
||||
ds_frame = frame.resize((320, 240), resample=Image.NEAREST)
|
||||
ds_frame = frame.resize((320, 240), resample=Image.Resampling.NEAREST)
|
||||
self.lores_mjpeg_stream.add_frame(_frame2bytes(ds_frame))
|
||||
|
||||
except Exception as e:
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue