Get new background detect running in simulation mode.

This commit is contained in:
Julian Stirling 2025-07-18 21:21:25 +01:00
parent fe1b84a922
commit eed3c44804
3 changed files with 16 additions and 21 deletions

View file

@ -158,23 +158,23 @@ class ColourChannelDetectLUV(BackgroundDetectAlgorithm):
def background_mask(self, image: np.ndarray) -> np.ndarray:
"""Calculate a binary image, showing whether each pixel is background.
True is background.
The image should be in LUV format, the output will be binary with the
same shape in the first two dimensions.
# human-intuitive way
"""
d = self.background_data
if not d:
raise RuntimeError(
"Background is not set: you need to calibrate background detection."
)
print(d)
# Only use the U and V channels of as brightness (L) often changes as the
# height of the sample changes.
return np.all(
np.abs(image[:, :, 1:] - np.array(d.means[1:])[np.newaxis, np.newaxis, :])
< np.array(d.standard_deviations[1:])[np.newaxis, np.newaxis, :]
* self.channel_tolerance,
* self.settings.channel_tolerance,
axis=2,
)
@ -189,6 +189,9 @@ class ColourChannelDetectLUV(BackgroundDetectAlgorithm):
"""
image_luv = cv2.cvtColor(image, cv2.COLOR_RGB2LUV)
mask = self.background_mask(image_luv)
print(np.count_nonzero(mask))
print(np.prod(mask.shape))
print((1 - np.count_nonzero(mask) / np.prod(mask.shape)) * 100)
return (1 - np.count_nonzero(mask) / np.prod(mask.shape)) * 100
def image_is_sample(self, image: np.ndarray) -> tuple[bool, str]:
@ -200,7 +203,7 @@ class ColourChannelDetectLUV(BackgroundDetectAlgorithm):
"""
sample_coverage = self.get_sample_coverage(image)
is_sample = sample_coverage > self.min_sample_coverage
is_sample = sample_coverage > self.settings.min_sample_coverage
message = f"{sample_coverage}% sample"
if not is_sample:
message = "only " + message

View file

@ -498,7 +498,7 @@ class BaseCamera(lt.Thing):
return self.active_detector.status
@lt.thing_setting
def background_detector_data(self) -> str:
def background_detector_data(self) -> dict:
"""The data for each background detector, used to save to disk."""
data = {}
for name, obj in self.background_detectors.items():
@ -511,9 +511,10 @@ class BaseCamera(lt.Thing):
"settings": obj.settings.model_dump(),
"background_data": bg_data,
}
return data
@detector_name.setter
def detector_name(self, data: str) -> None:
@background_detector_data.setter
def background_detector_data(self, data: dict) -> None:
"""Set the data for each detector. This should only be called on init.
Do not call over HTTP. Would be good to have a way to make this private.
@ -548,6 +549,8 @@ class BaseCamera(lt.Thing):
background = self.grab_jpeg(portal)
background = np.array(Image.open(background.open()))
self.active_detector.set_background(background)
# Manually save settings as the setter is not called.
self.save_settings()
CameraDependency = lt.deps.direct_thing_client_dependency(BaseCamera, "/camera/")