Source code for iris.nodes.validators.cross_object_validators
import numpy as np
from pydantic import Field
from iris.io.class_configs import Algorithm
from iris.io.dataclasses import EyeCenters, GeometryPolygons, IRImage
from iris.io.errors import ExtrapolatedPolygonsInsideImageValidatorError, EyeCentersInsideImageValidatorError
[docs]class EyeCentersInsideImageValidator(Algorithm):
"""Validate that the eye center are not too close to the border.
Raises:
EyeCentersInsideImageValidatorError: If pupil or iris center are strictly less than `min_distance_to_border`
pixel of the image boundary.
"""
[docs] class Parameters(Algorithm.Parameters):
"""Parameters class for EyeCentersInsideImageValidator objects."""
min_distance_to_border: float
__parameters_type__ = Parameters
def __init__(self, min_distance_to_border: float = 0.0) -> None:
"""Assign parameters.
Args:
min_distance_to_border (float, optional): Minimum allowed distance to image boundary.
Defaults to 0.0 (Eye centers can be at the image border).
"""
super().__init__(min_distance_to_border=min_distance_to_border)
[docs] def run(self, ir_image: IRImage, eye_centers: EyeCenters) -> None:
"""Validate if eye centers are within proper image boundaries.
Args:
ir_image (IRImage): IR image
eye_centers (EyeCenters): Eye centers
Raises:
EyeCentersInsideImageValidatorError: Raised if pupil or iris center is not in within correct image boundary.
"""
if not self._check_center_valid(eye_centers.pupil_x, eye_centers.pupil_y, ir_image):
raise EyeCentersInsideImageValidatorError("Pupil center is not in allowed image boundary.")
if not self._check_center_valid(eye_centers.iris_x, eye_centers.iris_y, ir_image):
raise EyeCentersInsideImageValidatorError("Iris center is not in allowed image boundary.")
def _check_center_valid(self, center_x: float, center_y: float, ir_image: IRImage) -> bool:
"""Check if center point is within proper image bound.
Args:
center_x (float): Center x
center_y (float): Center y
ir_image (IRImage): IR image object
Returns:
bool: Result of the check.
"""
return (
self.params.min_distance_to_border <= center_x <= ir_image.width - self.params.min_distance_to_border
and self.params.min_distance_to_border <= center_y <= ir_image.height - self.params.min_distance_to_border
)
[docs]class ExtrapolatedPolygonsInsideImageValidator(Algorithm):
"""Validate that GeometryPolygons are included within the image to a certain minimum percentage.
Raises:
ExtrapolatedPolygonsInsideImageValidatorError: If the number of points of the pupil/iris/eyeball
that are within the input image is below threshold.
"""
[docs] class Parameters(Algorithm.Parameters):
"""Parameters class for ExtrapolatedPolygonsInsideImageValidator objects."""
min_pupil_allowed_percentage: float = Field(..., ge=0.0, le=1.0)
min_iris_allowed_percentage: float = Field(..., ge=0.0, le=1.0)
min_eyeball_allowed_percentage: float = Field(..., ge=0.0, le=1.0)
__parameters_type__ = Parameters
def __init__(
self,
min_pupil_allowed_percentage: float = 0.0,
min_iris_allowed_percentage: float = 0.0,
min_eyeball_allowed_percentage: float = 0.0,
) -> None:
"""Assign parameters.
Args:
min_pupil_allowed_percentage (float, optional): Minimum allowed percentage of extrapolated pupil polygons that must be within an image.
Defaults to 0.0 (Entire extrapolated polygon may be outside of an image).
min_iris_allowed_percentage (float, optional): Minimum allowed percentage of extrapolated iris polygons that must be within an image.
Defaults to 0.0 (Entire extrapolated polygon may be outside of an image).
min_eyeball_allowed_percentage (float, optional): Minimum allowed percentage of extrapolated eyeball polygons that must be within an image.
Defaults to 0.0 (Entire extrapolated polygon may be outside of an image).
"""
super().__init__(
min_pupil_allowed_percentage=min_pupil_allowed_percentage,
min_iris_allowed_percentage=min_iris_allowed_percentage,
min_eyeball_allowed_percentage=min_eyeball_allowed_percentage,
)
[docs] def run(self, ir_image: IRImage, extrapolated_polygons: GeometryPolygons) -> None:
"""Perform validation.
Args:
ir_image (IRImage): IR image.
extrapolated_polygons (GeometryPolygons): Extrapolated polygons.
Raises:
ExtrapolatedPolygonsInsideImageValidatorError: Raised if not enough points of the pupil/iris/eyeball are within an image.
"""
if not self._check_correct_percentage(
extrapolated_polygons.pupil_array, self.params.min_pupil_allowed_percentage, ir_image
):
raise ExtrapolatedPolygonsInsideImageValidatorError("Not enough pupil points are within an image.")
if not self._check_correct_percentage(
extrapolated_polygons.iris_array, self.params.min_iris_allowed_percentage, ir_image
):
raise ExtrapolatedPolygonsInsideImageValidatorError("Not enough iris points are within an image.")
if not self._check_correct_percentage(
extrapolated_polygons.eyeball_array, self.params.min_eyeball_allowed_percentage, ir_image
):
raise ExtrapolatedPolygonsInsideImageValidatorError("Not enough eyeball points are within an image.")
def _check_correct_percentage(self, polygon: np.ndarray, min_allowed_percentage: float, ir_image: IRImage) -> bool:
"""Check percentage of points withing image based on minimal specified threshold.
Args:
polygon (np.ndarray): polygon to verify.
min_allowed_percentage (float): minimal allowed percentage of points that must be within an image.
ir_image (IRImage): ir image object.
Returns:
bool: Check result.
"""
num_points_inside_image: float = np.sum(
np.all(np.logical_and((0, 0) <= polygon, polygon <= (ir_image.width, ir_image.height)), axis=1)
)
percentage_points_inside_image = num_points_inside_image / len(polygon)
return percentage_points_inside_image >= min_allowed_percentage