implement and use cnt bgsub

This commit is contained in:
Blake Blackshear 2023-06-04 08:27:55 -05:00
parent 18318fbde0
commit 3b74c79919
2 changed files with 119 additions and 2 deletions

View File

@ -0,0 +1,117 @@
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,
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()
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

View File

@ -18,7 +18,7 @@ from frigate.config import CameraConfig, DetectConfig, PixelFormatEnum
from frigate.const import CACHE_DIR
from frigate.log import LogPipe
from frigate.motion import MotionDetector
from frigate.motion.frigate_motion import FrigateMotionDetector
from frigate.motion.cnt_motion import CNTMotionDetector
from frigate.object_detection import RemoteObjectDetector
from frigate.track import ObjectTracker
from frigate.track.norfair_tracker import NorfairTracker
@ -463,7 +463,7 @@ def track_camera(
objects_to_track = config.objects.track
object_filters = config.objects.filters
motion_detector = FrigateMotionDetector(
motion_detector = CNTMotionDetector(
frame_shape,
config.motion,
improve_contrast_enabled,