Added a new way to capture full res JPEGs, need to do a comparison of results

This commit is contained in:
jaknapper 2025-04-29 18:52:59 +01:00 committed by Julian Stirling
parent ab33de7ccd
commit 26163dc97e
3 changed files with 65 additions and 2 deletions

View file

@ -33,7 +33,7 @@ from labthings_fastapi.dependencies.invocation import InvocationLogger
from .camera import RawCameraDependency as Camera
from .camera import CameraDependency as WrappedCamera
from .stage import StageDependency as Stage
from .capture import CaptureThing
from .capture import CaptureThing, _save_capture
import numpy as np
from pydantic import BaseModel
@ -310,7 +310,27 @@ class AutofocusThing(Thing):
stack_dir,
f"{capture_count}.jpeg",
)
capture.capture_jpeg(filename=jpeg_path, cam=cam)
# The pre-existing capture_jpeg
# capture.capture_jpeg(filename=jpeg_path, cam=cam)
# A new way to get the full array
img = capture.capture_jpeg_array()
metadata = metadata_getter()
_save_capture(
jpeg_path,
img,
metadata,
logger
)
# The old capture and save a "main" res image
# capture._capture_and_save(
# jpeg_path=jpeg_path,
# cam=cam,
# logger=logger,
# metadata_getter=metadata_getter,
# )
# If the stack isn't complete yet, move
if capture_count + 1 < images_to_capture:

View file

@ -77,6 +77,11 @@ class CameraProtocol(Protocol):
"""Acquire one image from the preview stream and return its size"""
...
def capture_jpeg_array(
self,
):
...
class BaseCamera(Thing):
"""A Thing representing a camera
@ -170,6 +175,12 @@ class CameraStub(BaseCamera):
) -> NDArray:
raise NotImplementedError("Cameras must not inherit from CameraStub")
@thing_action
def capture_jpeg_array(
self,
):
raise NotImplementedError("Cameras must not inherit from CameraStub")
@thing_action
def capture_jpeg(
self,

View file

@ -54,6 +54,11 @@ class CaptureThing(Thing):
jpeg = cam.capture_jpeg(resolution="full")
jpeg.save(filename)
@thing_action
def capture_jpeg_array(self, cam: CamDep):
"""Return a full resolution stream array"""
return cam.capture_jpeg_array()
@thing_action
def _capture_array(self, cam: CamDep, metadata_getter: GetThingStates):
"""Capture an image in memory and return it with metadata
@ -94,3 +99,30 @@ class CaptureThing(Thing):
logger.warning(f"Failed to add metadata to {jpeg_path}")
except Exception as e:
raise IOError(f"An error occurred while saving {jpeg_path}") from e
def _save_capture(
jpeg_path: str,
image: np.ndarray,
metadata: dict,
logger: InvocationLogger,
) -> None:
"""Saving the captured image and metadata to disk
logger warning (via InvocationLogger) is raised if metadata is failed to be added
IOError is raised if the file cannot be saved
nothing is returned on success"""
try:
Image.fromarray(image.astype("uint8"), "RGB").save(
jpeg_path, quality=95, subsampling=0
)
try:
exif_dict = piexif.load(jpeg_path)
exif_dict["Exif"][piexif.ExifIFD.UserComment] = json.dumps(
metadata
).encode("utf-8")
piexif.insert(piexif.dump(exif_dict), jpeg_path)
except: # noqa: E722
# We need to capture any exception as there are many reasons metadata
# might not be added. We warn rather than log the error.
logger.warning(f"Failed to add metadata to {jpeg_path}")
except Exception as e:
raise IOError(f"An error occurred while saving {jpeg_path}") from e