update default motion config

This commit is contained in:
Blake Blackshear 2023-06-09 05:56:39 -05:00
parent a1dce08bfc
commit 59e5ed6a89
3 changed files with 11 additions and 135 deletions

View File

@ -261,33 +261,29 @@ motion:
# Optional: The threshold passed to cv2.threshold to determine if a pixel is different enough to be counted as motion. (default: shown below)
# Increasing this value will make motion detection less sensitive and decreasing it will make motion detection more sensitive.
# The value should be between 1 and 255.
threshold: 25
threshold: 40
# Optional: The percentage of the image used to detect lightning or other substantial changes where motion detection
# needs to recalibrate. (default: shown below)
# Increasing this value will make motion detection more likely to consider lightning or ir mode changes as valid motion.
# Decreasing this value will make motion detection more likely to ignore large amounts of motion such as a person approaching
# a doorbell camera.
lightning_threshold: 0.8
# Optional: Minimum size in pixels in the resized motion image that counts as motion (default: 30)
# Optional: Minimum size in pixels in the resized motion image that counts as motion (default: shown below)
# Increasing this value will prevent smaller areas of motion from being detected. Decreasing will
# make motion detection more sensitive to smaller moving objects.
# As a rule of thumb:
# - 15 - high sensitivity
# - 30 - medium sensitivity
# - 50 - low sensitivity
contour_area: 30
# Optional: Alpha value passed to cv2.accumulateWeighted when averaging the motion delta across multiple frames (default: shown below)
# Higher values mean the current frame impacts the delta a lot, and a single raindrop may register as motion.
# Too low and a fast moving person wont be detected as motion.
delta_alpha: 0.2
contour_area: 15
# Optional: Alpha value passed to cv2.accumulateWeighted when averaging frames to determine the background (default: shown below)
# Higher values mean the current frame impacts the average a lot, and a new object will be averaged into the background faster.
# Low values will cause things like moving shadows to be detected as motion for longer.
# https://www.geeksforgeeks.org/background-subtraction-in-an-image-using-concept-of-running-average/
frame_alpha: 0.2
frame_alpha: 0.02
# Optional: Height of the resized motion frame (default: 50)
# This operates as an efficient blur alternative. Higher values will result in more granular motion detection at the expense
# of higher CPU usage. Lower values result in less CPU, but small changes may not register as motion.
# Higher values will result in more granular motion detection at the expense of higher CPU usage.
# Lower values result in less CPU, but small changes may not register as motion.
frame_height: 50
# Optional: motion mask
# NOTE: see docs for more detailed info on creating masks
@ -295,7 +291,7 @@ motion:
# Optional: improve contrast (default: shown below)
# Enables dynamic contrast improvement. This should help improve night detections at the cost of making motion detection more sensitive
# for daytime.
improve_contrast: False
improve_contrast: True
# Optional: Delay when updating camera motion through MQTT from ON -> OFF (default: shown below).
mqtt_off_delay: 30

View File

@ -191,7 +191,7 @@ class RecordConfig(FrigateBaseModel):
class MotionConfig(FrigateBaseModel):
threshold: int = Field(
default=25,
default=40,
title="Motion detection threshold (1-255).",
ge=1,
le=255,
@ -199,10 +199,10 @@ class MotionConfig(FrigateBaseModel):
lightning_threshold: float = Field(
default=0.8, title="Lightning detection threshold (0.3-1.0).", ge=0.3, le=1.0
)
improve_contrast: bool = Field(default=False, title="Improve Contrast")
contour_area: Optional[int] = Field(default=30, title="Contour Area")
improve_contrast: bool = Field(default=True, title="Improve Contrast")
contour_area: Optional[int] = Field(default=15, title="Contour Area")
delta_alpha: float = Field(default=0.2, title="Delta Alpha")
frame_alpha: float = Field(default=0.2, title="Frame Alpha")
frame_alpha: float = Field(default=0.02, title="Frame Alpha")
frame_height: Optional[int] = Field(default=50, title="Frame Height")
mask: Union[str, List[str]] = Field(
default="", title="Coordinates polygon for the motion mask."

View File

@ -1,120 +0,0 @@
from typing import Tuple
import cv2
import imutils
import numpy as np
from frigate.config import MotionConfig
from frigate.motion import MotionDetector
class CNTMotionDetector(MotionDetector):
def __init__(
self,
frame_shape: Tuple[int, int, int],
config: MotionConfig,
fps: int,
improve_contrast,
threshold,
contour_area,
):
self.frame_shape = frame_shape
self.threshold = threshold
self.contour_area = contour_area
self.improve_contrast = improve_contrast
self.resize_factor = frame_shape[0] / config.frame_height
self.motion_frame_size = (
config.frame_height,
config.frame_height * frame_shape[1] // frame_shape[0],
)
resized_mask = cv2.resize(
config.mask,
dsize=(self.motion_frame_size[1], self.motion_frame_size[0]),
interpolation=cv2.INTER_LINEAR,
)
self.blur_kernel = (
3, # int(0.05 * self.motion_frame_size[0]),
3, # int(0.05 * self.motion_frame_size[0]),
)
self.mask = np.where(resized_mask == [0])
# createBackgroundSubtractorCNT(int minPixelStability = 15,
# bool useHistory = true,
# int maxPixelStability = 15*60,
# bool isParallel = true);
self.bg_subtractor = cv2.bgsegm.createBackgroundSubtractorCNT(
fps, True, fps * 60, True
)
self.save_images = False
self.frame_counter = 0
def detect(self, frame):
motion_boxes = []
gray = frame[0 : self.frame_shape[0], 0 : self.frame_shape[1]]
# resize frame
resized_frame = cv2.resize(
gray,
dsize=(self.motion_frame_size[1], self.motion_frame_size[0]),
interpolation=cv2.INTER_LINEAR,
)
if self.improve_contrast.value:
resized_frame = cv2.equalizeHist(resized_frame)
blurred_frame = cv2.GaussianBlur(
resized_frame, self.blur_kernel, cv2.BORDER_DEFAULT
)
# mask frame
blurred_frame[self.mask] = [255]
fg = self.bg_subtractor.apply(blurred_frame)
thresh = cv2.threshold(fg, self.threshold.value, 255, cv2.THRESH_BINARY)[1]
# dilate the thresholded image to fill in holes, then find contours
# on thresholded image
cnts = cv2.findContours(thresh, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
cnts = imutils.grab_contours(cnts)
# loop over the contours
for c in cnts:
# if the contour is big enough, count it as motion
contour_area = cv2.contourArea(c)
if contour_area > self.contour_area.value:
x, y, w, h = cv2.boundingRect(c)
motion_boxes.append(
(
int(x * self.resize_factor),
int(y * self.resize_factor),
int((x + w) * self.resize_factor),
int((y + h) * self.resize_factor),
)
)
if self.save_images:
self.frame_counter += 1
# print("--------")
# print(self.frame_counter)
thresh_boxes = cv2.cvtColor(fg, cv2.COLOR_GRAY2BGR)
for c in cnts:
contour_area = cv2.contourArea(c)
if contour_area > self.contour_area.value:
x, y, w, h = cv2.boundingRect(c)
cv2.rectangle(
thresh_boxes,
(x, y),
(x + w, y + h),
(0, 0, 255),
2,
)
# print("--------")
image_row_1 = cv2.hconcat(
[
cv2.cvtColor(fg, cv2.COLOR_GRAY2BGR),
cv2.cvtColor(
self.bg_subtractor.getBackgroundImage(), cv2.COLOR_GRAY2BGR
),
]
)
image_row_2 = cv2.hconcat(
[cv2.cvtColor(thresh, cv2.COLOR_GRAY2BGR), thresh_boxes]
)
combined_image = cv2.vconcat([image_row_1, image_row_2])
cv2.imwrite(f"debug/frames/motion-{self.frame_counter}.jpg", combined_image)
return motion_boxes