Added a new way to capture full res JPEGs, need to do a comparison of results
This commit is contained in:
parent
ab33de7ccd
commit
26163dc97e
3 changed files with 65 additions and 2 deletions
|
|
@ -33,7 +33,7 @@ from labthings_fastapi.dependencies.invocation import InvocationLogger
|
||||||
from .camera import RawCameraDependency as Camera
|
from .camera import RawCameraDependency as Camera
|
||||||
from .camera import CameraDependency as WrappedCamera
|
from .camera import CameraDependency as WrappedCamera
|
||||||
from .stage import StageDependency as Stage
|
from .stage import StageDependency as Stage
|
||||||
from .capture import CaptureThing
|
from .capture import CaptureThing, _save_capture
|
||||||
import numpy as np
|
import numpy as np
|
||||||
from pydantic import BaseModel
|
from pydantic import BaseModel
|
||||||
|
|
||||||
|
|
@ -310,7 +310,27 @@ class AutofocusThing(Thing):
|
||||||
stack_dir,
|
stack_dir,
|
||||||
f"{capture_count}.jpeg",
|
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 the stack isn't complete yet, move
|
||||||
if capture_count + 1 < images_to_capture:
|
if capture_count + 1 < images_to_capture:
|
||||||
|
|
|
||||||
|
|
@ -77,6 +77,11 @@ class CameraProtocol(Protocol):
|
||||||
"""Acquire one image from the preview stream and return its size"""
|
"""Acquire one image from the preview stream and return its size"""
|
||||||
...
|
...
|
||||||
|
|
||||||
|
def capture_jpeg_array(
|
||||||
|
self,
|
||||||
|
):
|
||||||
|
...
|
||||||
|
|
||||||
|
|
||||||
class BaseCamera(Thing):
|
class BaseCamera(Thing):
|
||||||
"""A Thing representing a camera
|
"""A Thing representing a camera
|
||||||
|
|
@ -170,6 +175,12 @@ class CameraStub(BaseCamera):
|
||||||
) -> NDArray:
|
) -> NDArray:
|
||||||
raise NotImplementedError("Cameras must not inherit from CameraStub")
|
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
|
@thing_action
|
||||||
def capture_jpeg(
|
def capture_jpeg(
|
||||||
self,
|
self,
|
||||||
|
|
|
||||||
|
|
@ -54,6 +54,11 @@ class CaptureThing(Thing):
|
||||||
jpeg = cam.capture_jpeg(resolution="full")
|
jpeg = cam.capture_jpeg(resolution="full")
|
||||||
jpeg.save(filename)
|
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
|
@thing_action
|
||||||
def _capture_array(self, cam: CamDep, metadata_getter: GetThingStates):
|
def _capture_array(self, cam: CamDep, metadata_getter: GetThingStates):
|
||||||
"""Capture an image in memory and return it with metadata
|
"""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}")
|
logger.warning(f"Failed to add metadata to {jpeg_path}")
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
raise IOError(f"An error occurred while saving {jpeg_path}") from 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
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue