Add minimum standard deviations for ColourChannelDetectLUV

This commit is contained in:
Julian Stirling 2025-11-17 15:58:53 +00:00
parent a2a6d870e2
commit 1f2099e46f

View file

@ -10,7 +10,6 @@ import cv2
import numpy as np import numpy as np
from pydantic import BaseModel, Field, ConfigDict from pydantic import BaseModel, Field, ConfigDict
from pydantic.errors import PydanticUserError from pydantic.errors import PydanticUserError
from scipy.stats import norm
from labthings_fastapi.thing_description import type_to_dataschema from labthings_fastapi.thing_description import type_to_dataschema
@ -144,7 +143,7 @@ class BackgroundDetectAlgorithm:
"Each background detect algorithm must implement an image_is_sample method." "Each background detect algorithm must implement an image_is_sample method."
) )
def set_background(self, image: np.ndarray) -> BaseModel: def set_background(self, image: np.ndarray) -> None:
"""Use the input image to update the background data. """Use the input image to update the background data.
Background data must be a Pydantic BaseModel. Background data must be a Pydantic BaseModel.
@ -196,6 +195,10 @@ class ColourChannelDetectLUV(BackgroundDetectAlgorithm):
background_data_model: BaseModel = ChannelDistributions background_data_model: BaseModel = ChannelDistributions
settings_data_model: BaseModel = ColourChannelDetectSettings settings_data_model: BaseModel = ColourChannelDetectSettings
# These are the same as those used for ChannelDeviationLUV. More detail is
# provided there.
min_stds = [0.5, 0.3, 0.5]
def background_mask(self, image: np.ndarray) -> np.ndarray: def background_mask(self, image: np.ndarray) -> np.ndarray:
"""Calculate a binary image, showing whether each pixel is background. """Calculate a binary image, showing whether each pixel is background.
@ -258,14 +261,12 @@ class ColourChannelDetectLUV(BackgroundDetectAlgorithm):
"""Use the input image to update the background distributions.""" """Use the input image to update the background distributions."""
image_luv = cv2.cvtColor(image, cv2.COLOR_RGB2LUV) image_luv = cv2.cvtColor(image, cv2.COLOR_RGB2LUV)
ch1 = (image_luv.T[0]).flatten() mu = np.mean(image_luv, axis=(0, 1))
ch2 = (image_luv.T[1]).flatten() std = np.std(image_luv, axis=(0, 1))
ch3 = (image_luv.T[2]).flatten()
points = np.array([np.asarray(ch1), np.asarray(ch2), np.asarray(ch3)]).T if np.any(std == 0):
raise ChannelBlankError("Some LUV channels have no standard devaition.")
# Get the mean and standard deviation of values in each channel std = np.maximum(std, self.min_stds)
mu, std = np.apply_along_axis(norm.fit, 0, points)
self.background_data = ChannelDistributions( self.background_data = ChannelDistributions(
means=mu.tolist(), standard_deviations=std.tolist() means=mu.tolist(), standard_deviations=std.tolist()