From 427116d19b86e20c4045cfeaa7f06100de3ae049 Mon Sep 17 00:00:00 2001 From: Felix Scheffer Date: Thu, 2 May 2024 22:04:51 +0200 Subject: [PATCH 1/2] fixes name of variable _learning_rate --- dvr_scan/scanner.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dvr_scan/scanner.py b/dvr_scan/scanner.py index 5b577ad..8c0d009 100644 --- a/dvr_scan/scanner.py +++ b/dvr_scan/scanner.py @@ -236,7 +236,7 @@ def __init__(self, self._threshold = 0.15 # -t/--threshold self._kernel_size = None # -k/--kernel-size self._downscale_factor = 1 # -df/--downscale-factor - self._learningRate = -1 # learning-rate + self._learning_rate = -1 # learning-rate self._max_threshold = 255.0 # max-threshold # Motion Event Parameters (set_event_params) From 23dc72ac423d5d287c07842bf8b2d73111751986 Mon Sep 17 00:00:00 2001 From: Felix Scheffer Date: Thu, 9 May 2024 01:20:46 +0200 Subject: [PATCH 2/2] adds variance-threshold setting --- docs/docs.md | 10 ++++++++++ dvr-scan.cfg | 6 ++++++ dvr_scan/cli/config.py | 1 + dvr_scan/cli/controller.py | 1 + dvr_scan/scanner.py | 12 +++++++++--- dvr_scan/subtractor.py | 5 +++-- 6 files changed, 30 insertions(+), 5 deletions(-) diff --git a/docs/docs.md b/docs/docs.md index ff7b7d4..04740f5 100644 --- a/docs/docs.md +++ b/docs/docs.md @@ -366,6 +366,16 @@ The following options control motion detection. A more comprehensive descriptio ``` + *
variance-threshold
+ Threshold on the distance between the pixel and the model to decide whether a pixel is well described by the background model. This parameter does not affect + the background update.
+ The threshold is not used by the CNT subtractor. + + ``` + variance-threshold = 16 + ``` + + *
kernel-size
Size (in pixels) of the noise reduction kernel. Size must be an odd number starting from 3, 0 to disable, or -1 to auto-set based on video resolution. diff --git a/dvr-scan.cfg b/dvr-scan.cfg index 3790f31..b8f1ccd 100644 --- a/dvr-scan.cfg +++ b/dvr-scan.cfg @@ -92,6 +92,12 @@ # will not update the model at all, and 1.0 would re-initialize it on every frame. #learning-rate = -1 +# Threshold on the distance between the pixel and the model to decide whether +# a pixel is well described by the background model. This parameter does not affect +# the background update. +# The threshold is not used by the CNT subtractor. +#variance-threshold = 16 + # Size (in pixels) of the noise reduction kernel. Can be odd integer starting # from 3, 0 to disable, or -1 to auto-set using video resolution. #kernel-size = -1 diff --git a/dvr_scan/cli/config.py b/dvr_scan/cli/config.py index dbce79c..3f253cb 100644 --- a/dvr_scan/cli/config.py +++ b/dvr_scan/cli/config.py @@ -320,6 +320,7 @@ def from_config(config_value: str, default: 'RGBValue') -> 'RGBValue': 'bg-subtractor': 'MOG2', 'threshold': 0.15, 'max-threshold': 255.0, + 'variance-threshold': 16.0, 'kernel-size': KernelSizeValue(), 'downscale-factor': 0, 'learning-rate': float(-1), diff --git a/dvr_scan/cli/controller.py b/dvr_scan/cli/controller.py index 8e48f31..da00a8b 100644 --- a/dvr_scan/cli/controller.py +++ b/dvr_scan/cli/controller.py @@ -272,6 +272,7 @@ def run_dvr_scan(settings: ProgramSettings) -> ty.List[ty.Tuple[FrameTimecode, F detector_type=DetectorType[settings.get('bg-subtractor').upper()], threshold=settings.get('threshold'), max_threshold=settings.get('max-threshold'), + variance_threshold=settings.get('variance-threshold'), kernel_size=settings.get('kernel-size'), downscale_factor=settings.get('downscale-factor'), learning_rate=settings.get('learning-rate'), diff --git a/dvr_scan/scanner.py b/dvr_scan/scanner.py index 8c0d009..0a12c9a 100644 --- a/dvr_scan/scanner.py +++ b/dvr_scan/scanner.py @@ -234,9 +234,10 @@ def __init__(self, # Motion Detection Parameters (set_detection_params) self._subtractor_type = DetectorType.MOG2 # -b/--bg-subtractor self._threshold = 0.15 # -t/--threshold + self._variance_threshold = 16.0 # variance-threshold self._kernel_size = None # -k/--kernel-size self._downscale_factor = 1 # -df/--downscale-factor - self._learning_rate = -1 # learning-rate + self._learning_rate = -1 # learning-rate self._max_threshold = 255.0 # max-threshold # Motion Event Parameters (set_event_params) @@ -364,6 +365,7 @@ def set_detection_params( detector_type: DetectorType = DetectorType.MOG2, threshold: float = 0.15, max_threshold: float = 255.0, + variance_threshold: float = 16.0, kernel_size: int = -1, downscale_factor: int = 1, learning_rate: float = -1, @@ -377,6 +379,7 @@ def set_detection_params( self._downscale_factor = max(downscale_factor, 1) assert kernel_size == -1 or kernel_size == 0 or kernel_size >= 3 self._kernel_size = kernel_size + self._variance_threshold = variance_threshold # TODO: Also allow ability to customize history size, as this is another factor that # influences how quickly the background model is updated. When calculated automatically, # OpenCV sets learning rate as: @@ -573,16 +576,19 @@ def scan(self) -> Optional[DetectionResult]: # Create background subtractor and motion detector. detector = MotionDetector( subtractor=self._subtractor_type.value( - kernel_size=kernel_size, learning_rate=self._learning_rate), + variance_threshold=self._variance_threshold, + kernel_size=kernel_size, + learning_rate=self._learning_rate), frame_size=self._input.resolution, downscale=self._downscale_factor, regions=self._regions) logger.info( - 'Using subtractor %s with kernel_size = %s%s and learning_rate = %s', + 'Using subtractor %s with kernel_size = %s%s, variance_threshold = %s and learning_rate = %s', self._subtractor_type.name, str(kernel_size) if kernel_size else 'off', ' (auto)' if self._kernel_size == -1 else '', + str(self._variance_threshold) if self._variance_threshold != 16.0 else 'auto', str(self._learning_rate) if self._learning_rate != -1 else 'auto', ) diff --git a/dvr_scan/subtractor.py b/dvr_scan/subtractor.py index cd12daa..f9e84ba 100644 --- a/dvr_scan/subtractor.py +++ b/dvr_scan/subtractor.py @@ -51,7 +51,7 @@ def __init__( self, kernel_size: int, history: int = 500, - variance_threshold: int = 16, + variance_threshold: float = 16.0, detect_shadows: bool = False, learning_rate: float = -1, ): @@ -93,6 +93,7 @@ def __init__( max_pixel_stability: int = 15 * 60, is_parallel: bool = True, learning_rate: float = -1, + variance_threshold = None, ): if kernel_size < 0 or (kernel_size > 1 and kernel_size % 2 == 0): raise ValueError("kernel_size must be odd integer >= 1 or zero (0)") @@ -118,7 +119,7 @@ def __init__( self, kernel_size: int, history: int = 500, - variance_threshold: int = 16, + variance_threshold: float = 16.0, detect_shadows: bool = False, learning_rate: float = -1, ):