diff --git a/frigate/motion/frigate_motion.py b/frigate/motion/frigate_motion.py index d49b0e861..8a067e1da 100644 --- a/frigate/motion/frigate_motion.py +++ b/frigate/motion/frigate_motion.py @@ -1,7 +1,9 @@ +from typing import Any + import cv2 import numpy as np -from frigate.config import MotionConfig +from frigate.config.config import RuntimeMotionConfig from frigate.motion import MotionDetector from frigate.util.image import grab_cv2_contours @@ -9,19 +11,20 @@ from frigate.util.image import grab_cv2_contours class FrigateMotionDetector(MotionDetector): def __init__( self, - frame_shape, - config: MotionConfig, + frame_shape: tuple[int, ...], + config: RuntimeMotionConfig, fps: int, - improve_contrast, - threshold, - contour_area, - ): + improve_contrast: Any, + threshold: Any, + contour_area: Any, + ) -> None: self.config = config self.frame_shape = frame_shape - self.resize_factor = frame_shape[0] / config.frame_height + frame_height = config.frame_height or frame_shape[0] + self.resize_factor = frame_shape[0] / frame_height self.motion_frame_size = ( - config.frame_height, - config.frame_height * frame_shape[1] // frame_shape[0], + frame_height, + frame_height * frame_shape[1] // frame_shape[0], ) self.avg_frame = np.zeros(self.motion_frame_size, np.float32) self.avg_delta = np.zeros(self.motion_frame_size, np.float32) @@ -38,10 +41,10 @@ class FrigateMotionDetector(MotionDetector): self.threshold = threshold self.contour_area = contour_area - def is_calibrating(self): + def is_calibrating(self) -> bool: return False - def detect(self, frame): + def detect(self, frame: np.ndarray) -> list: motion_boxes = [] gray = frame[0 : self.frame_shape[0], 0 : self.frame_shape[1]] @@ -99,7 +102,7 @@ class FrigateMotionDetector(MotionDetector): # dilate the thresholded image to fill in holes, then find contours # on thresholded image - thresh_dilated = cv2.dilate(thresh, None, iterations=2) + thresh_dilated = cv2.dilate(thresh, None, iterations=2) # type: ignore[call-overload] contours = cv2.findContours( thresh_dilated, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE ) diff --git a/frigate/motion/improved_motion.py b/frigate/motion/improved_motion.py index b821e9532..21ef99620 100644 --- a/frigate/motion/improved_motion.py +++ b/frigate/motion/improved_motion.py @@ -4,8 +4,11 @@ import cv2 import numpy as np from scipy.ndimage import gaussian_filter +from typing import Any, Optional + from frigate.camera import PTZMetrics from frigate.config import MotionConfig +from frigate.config.config import RuntimeMotionConfig from frigate.motion import MotionDetector from frigate.util.image import grab_cv2_contours @@ -15,22 +18,23 @@ logger = logging.getLogger(__name__) class ImprovedMotionDetector(MotionDetector): def __init__( self, - frame_shape, - config: MotionConfig, + frame_shape: tuple[int, ...], + config: RuntimeMotionConfig, fps: int, - ptz_metrics: PTZMetrics = None, - name="improved", - blur_radius=1, - interpolation=cv2.INTER_NEAREST, - contrast_frame_history=50, - ): + ptz_metrics: Optional[PTZMetrics] = None, + name: str = "improved", + blur_radius: int = 1, + interpolation: int = cv2.INTER_NEAREST, + contrast_frame_history: int = 50, + ) -> None: self.name = name self.config = config self.frame_shape = frame_shape - self.resize_factor = frame_shape[0] / config.frame_height + frame_height = config.frame_height or frame_shape[0] + self.resize_factor = frame_shape[0] / frame_height self.motion_frame_size = ( - config.frame_height, - config.frame_height * frame_shape[1] // frame_shape[0], + frame_height, + frame_height * frame_shape[1] // frame_shape[0], ) self.avg_frame = np.zeros(self.motion_frame_size, np.float32) self.motion_frame_count = 0 @@ -44,20 +48,20 @@ class ImprovedMotionDetector(MotionDetector): self.contrast_values[:, 1:2] = 255 self.contrast_values_index = 0 self.ptz_metrics = ptz_metrics - self.last_stop_time = None + self.last_stop_time: float | None = None - def is_calibrating(self): + def is_calibrating(self) -> bool: return self.calibrating - def detect(self, frame): - motion_boxes = [] + def detect(self, frame: np.ndarray) -> list[tuple[int, int, int, int]]: + motion_boxes: list[tuple[int, int, int, int]] = [] if not self.config.enabled: return motion_boxes # if ptz motor is moving from autotracking, quickly return # a single box that is 80% of the frame - if ( + if self.ptz_metrics is not None and ( self.ptz_metrics.autotracker_enabled.value and not self.ptz_metrics.motor_stopped.is_set() ): @@ -130,19 +134,19 @@ class ImprovedMotionDetector(MotionDetector): # dilate the thresholded image to fill in holes, then find contours # on thresholded image - thresh_dilated = cv2.dilate(thresh, None, iterations=1) + thresh_dilated = cv2.dilate(thresh, None, iterations=1) # type: ignore[call-overload] contours = cv2.findContours( thresh_dilated, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE ) contours = grab_cv2_contours(contours) # loop over the contours - total_contour_area = 0 + total_contour_area: float = 0 for c in contours: # if the contour is big enough, count it as motion contour_area = cv2.contourArea(c) total_contour_area += contour_area - if contour_area > self.config.contour_area: + if contour_area > (self.config.contour_area or 0): x, y, w, h = cv2.boundingRect(c) motion_boxes.append( ( @@ -159,7 +163,7 @@ class ImprovedMotionDetector(MotionDetector): # check if the motor has just stopped from autotracking # if so, reassign the average to the current frame so we begin with a new baseline - if ( + if self.ptz_metrics is not None and ( # ensure we only do this for cameras with autotracking enabled self.ptz_metrics.autotracker_enabled.value and self.ptz_metrics.motor_stopped.is_set() diff --git a/frigate/mypy.ini b/frigate/mypy.ini index e1da675be..2341dc629 100644 --- a/frigate/mypy.ini +++ b/frigate/mypy.ini @@ -47,7 +47,7 @@ ignore_errors = false [mypy-frigate.jobs.*] ignore_errors = false -[mypy-frigate.motion] +[mypy-frigate.motion.*] ignore_errors = false [mypy-frigate.object_detection]