Merge branch 'simulation-axes' into 'v3'
Defocus and realign simulation axes See merge request openflexure/openflexure-microscope-server!282
This commit is contained in:
commit
13c63f8481
1 changed files with 24 additions and 10 deletions
|
|
@ -17,6 +17,7 @@ import time
|
||||||
import cv2
|
import cv2
|
||||||
import numpy as np
|
import numpy as np
|
||||||
import piexif
|
import piexif
|
||||||
|
from scipy.ndimage import gaussian_filter
|
||||||
|
|
||||||
from labthings_fastapi.utilities import get_blocking_portal
|
from labthings_fastapi.utilities import get_blocking_portal
|
||||||
from labthings_fastapi.decorators import thing_action, thing_property
|
from labthings_fastapi.decorators import thing_action, thing_property
|
||||||
|
|
@ -29,6 +30,10 @@ from pydantic import RootModel
|
||||||
from . import BaseCamera, JPEGBlob
|
from . import BaseCamera, JPEGBlob
|
||||||
from ..stage import StageProtocol as Stage
|
from ..stage import StageProtocol as Stage
|
||||||
|
|
||||||
|
# The ratio between "motor" steps and pixels
|
||||||
|
# higher related to a faster movement
|
||||||
|
RATIO = 0.2
|
||||||
|
|
||||||
|
|
||||||
class ArrayModel(RootModel):
|
class ArrayModel(RootModel):
|
||||||
"""A model for an array"""
|
"""A model for an array"""
|
||||||
|
|
@ -95,15 +100,24 @@ class SimulatedCamera(BaseCamera):
|
||||||
int(y) - h // 2 : int(y) - h // 2 + h,
|
int(y) - h // 2 : int(y) - h // 2 + h,
|
||||||
] -= self.sprites[int(sprite)]
|
] -= self.sprites[int(sprite)]
|
||||||
|
|
||||||
def generate_image(self, pos: tuple[int, int]):
|
def generate_image(self, pos: tuple[int, int, int]):
|
||||||
"""Generate an image with blobs based on supplied coordinates"""
|
"""Generate an image with blobs based on supplied coordinates"""
|
||||||
cw, ch, _ = self.canvas_shape
|
canvas_width, canvas_height, _ = self.canvas_shape
|
||||||
w, h, _ = self.shape
|
image_width, image_height, _ = self.shape
|
||||||
tl = (int(pos[0]) - w // 2 - cw // 2, int(pos[1]) - h // 2 - ch // 2)
|
pos = tuple(x * RATIO for x in pos)
|
||||||
image = self.canvas[
|
top_left = (
|
||||||
tuple(slice(tl[i], tl[i] + self.shape[i]) for i in range(2))
|
int(pos[0]) - image_width // 2 - canvas_width // 2,
|
||||||
+ (slice(None),)
|
int(pos[1]) - image_height // 2 - canvas_height // 2,
|
||||||
]
|
)
|
||||||
|
x_slice = slice(top_left[0], top_left[0] + self.shape[0])
|
||||||
|
y_slice = slice(top_left[1], top_left[1] + self.shape[1])
|
||||||
|
z_slice = slice(None)
|
||||||
|
focused_image = self.canvas[(x_slice, y_slice, z_slice)]
|
||||||
|
image = gaussian_filter(
|
||||||
|
focused_image,
|
||||||
|
sigma=np.abs(pos[2]) / 5,
|
||||||
|
axes=(0, 1),
|
||||||
|
)
|
||||||
if image.shape != self.shape:
|
if image.shape != self.shape:
|
||||||
raise ValueError(
|
raise ValueError(
|
||||||
f"Image shape {image.shape} does not match intended shape {self.shape}"
|
f"Image shape {image.shape} does not match intended shape {self.shape}"
|
||||||
|
|
@ -125,8 +139,8 @@ class SimulatedCamera(BaseCamera):
|
||||||
pos = self.get_stage_position()
|
pos = self.get_stage_position()
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
print(f"Failed to get stage position: {e}")
|
print(f"Failed to get stage position: {e}")
|
||||||
pos = {"x": 0, "y": 0}
|
pos = {"x": 0, "y": 0, "z": 0}
|
||||||
return self.generate_image((pos["x"] / 10, pos["y"] / 10))
|
return self.generate_image((pos["y"], pos["x"], pos["z"]))
|
||||||
|
|
||||||
def __enter__(self):
|
def __enter__(self):
|
||||||
self._capture_enabled = True
|
self._capture_enabled = True
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue