Преглед на файлове

no longer make motion settings dynamic

Blake Blackshear преди 3 години
родител
ревизия
294c79a271
променени са 3 файла, в които са добавени 52 реда и са изтрити 25 реда
  1. 12 8
      docs/docs/configuration/index.md
  2. 2 9
      frigate/config.py
  3. 38 8
      frigate/motion.py

+ 12 - 8
docs/docs/configuration/index.md

@@ -194,10 +194,14 @@ motion:
   # 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
-  # Optional: Minimum size in pixels in the resized motion image that counts as motion (default: ~0.17% of the motion frame area)
-  # Increasing this value will prevent smaller areas of motion from being detected. Decreasing will make motion detection more sensitive to smaller
-  # moving objects.
-  contour_area: 100
+  # Optional: Minimum size in pixels in the resized motion image that counts as motion (default: 30)
+  # 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.
@@ -207,10 +211,10 @@ motion:
   # 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
-  # Optional: Height of the resized motion frame  (default: 1/6th of the original frame height, but no less than 180)
-  # 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.
-  frame_height: 180
+  # Optional: Height of the resized motion frame  (default: 80)
+  # 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.
+  frame_height: 50
   # Optional: motion mask
   # NOTE: see docs for more detailed info on creating masks
   mask: 0,900,1080,900,1080,1920,0,1920

+ 2 - 9
frigate/config.py

@@ -103,10 +103,10 @@ class MotionConfig(FrigateBaseModel):
         ge=1,
         le=255,
     )
-    contour_area: Optional[int] = Field(title="Contour Area")
+    contour_area: Optional[int] = Field(default=30, title="Contour Area")
     delta_alpha: float = Field(default=0.2, title="Delta Alpha")
     frame_alpha: float = Field(default=0.2, title="Frame Alpha")
-    frame_height: Optional[int] = Field(title="Frame Height")
+    frame_height: Optional[int] = Field(default=50, title="Frame Height")
     mask: Union[str, List[str]] = Field(
         default="", title="Coordinates polygon for the motion mask."
     )
@@ -119,13 +119,6 @@ class RuntimeMotionConfig(MotionConfig):
     def __init__(self, **config):
         frame_shape = config.get("frame_shape", (1, 1))
 
-        if "frame_height" not in config:
-            config["frame_height"] = frame_shape[0] // 6
-
-        if "contour_area" not in config:
-            frame_width = frame_shape[1] * config["frame_height"] / frame_shape[0]
-            config["contour_area"] = config["frame_height"] * frame_width * 0.004
-
         mask = config.get("mask", "")
         config["raw_mask"] = mask
 

+ 38 - 8
frigate/motion.py

@@ -23,6 +23,7 @@ class MotionDetector:
             interpolation=cv2.INTER_LINEAR,
         )
         self.mask = np.where(resized_mask == [0])
+        self.save_images = False
 
     def detect(self, frame):
         motion_boxes = []
@@ -37,16 +38,13 @@ class MotionDetector:
         )
 
         # Improve contrast
-        minval = np.percentile(resized_frame, 5)
-        maxval = np.percentile(resized_frame, 95)
+        minval = np.percentile(resized_frame, 4)
+        maxval = np.percentile(resized_frame, 96)
         resized_frame = np.clip(resized_frame, minval, maxval)
         resized_frame = (((resized_frame - minval) / (maxval - minval)) * 255).astype(
             np.uint8
         )
 
-        # convert to grayscale
-        # resized_frame = cv2.cvtColor(resized_frame, cv2.COLOR_BGR2GRAY)
-
         # mask frame
         resized_frame[self.mask] = [255]
 
@@ -55,6 +53,8 @@ class MotionDetector:
         if self.frame_counter < 30:
             self.frame_counter += 1
         else:
+            if self.save_images:
+                self.frame_counter += 1
             # compare to average
             frameDelta = cv2.absdiff(resized_frame, cv2.convertScaleAbs(self.avg_frame))
 
@@ -64,7 +64,6 @@ class MotionDetector:
             cv2.accumulateWeighted(frameDelta, self.avg_delta, self.config.delta_alpha)
 
             # compute the threshold image for the current frame
-            # TODO: threshold
             current_thresh = cv2.threshold(
                 frameDelta, self.config.threshold, 255, cv2.THRESH_BINARY
             )[1]
@@ -81,8 +80,10 @@ class MotionDetector:
 
             # dilate the thresholded image to fill in holes, then find contours
             # on thresholded image
-            thresh = cv2.dilate(thresh, None, iterations=2)
-            cnts = cv2.findContours(thresh, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
+            thresh_dilated = cv2.dilate(thresh, None, iterations=2)
+            cnts = cv2.findContours(
+                thresh_dilated, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE
+            )
             cnts = imutils.grab_contours(cnts)
 
             # loop over the contours
@@ -100,6 +101,35 @@ class MotionDetector:
                         )
                     )
 
+            if self.save_images:
+                thresh_dilated = cv2.cvtColor(thresh_dilated, cv2.COLOR_GRAY2BGR)
+                # print("--------")
+                # print(self.frame_counter)
+                for c in cnts:
+                    contour_area = cv2.contourArea(c)
+                    # print(contour_area)
+                    if contour_area > self.config.contour_area:
+                        x, y, w, h = cv2.boundingRect(c)
+                        cv2.rectangle(
+                            thresh_dilated,
+                            (x, y),
+                            (x + w, y + h),
+                            (0, 0, 255),
+                            2,
+                        )
+                # print("--------")
+                image_row_1 = cv2.hconcat(
+                    [
+                        cv2.cvtColor(frameDelta, cv2.COLOR_GRAY2BGR),
+                        cv2.cvtColor(avg_delta_image, cv2.COLOR_GRAY2BGR),
+                    ]
+                )
+                image_row_2 = cv2.hconcat(
+                    [cv2.cvtColor(thresh, cv2.COLOR_GRAY2BGR), thresh_dilated]
+                )
+                combined_image = cv2.vconcat([image_row_1, image_row_2])
+                cv2.imwrite(f"motion/motion-{self.frame_counter}.jpg", combined_image)
+
         if len(motion_boxes) > 0:
             self.motion_frame_count += 1
             if self.motion_frame_count >= 10: