2022-11-04 03:23:09 +01:00
|
|
|
import unittest
|
2022-12-15 14:12:52 +01:00
|
|
|
from unittest.mock import Mock, patch
|
2022-11-04 03:23:09 +01:00
|
|
|
|
|
|
|
import numpy as np
|
2022-12-15 14:12:52 +01:00
|
|
|
from pydantic import parse_obj_as
|
|
|
|
|
|
|
|
from frigate.config import DetectorConfig, InputTensorEnum, ModelConfig
|
|
|
|
from frigate.detectors import DetectorTypeEnum
|
|
|
|
import frigate.detectors as detectors
|
2022-11-04 03:23:09 +01:00
|
|
|
import frigate.object_detection
|
|
|
|
|
|
|
|
|
|
|
|
class TestLocalObjectDetector(unittest.TestCase):
|
2022-12-15 14:12:52 +01:00
|
|
|
def test_localdetectorprocess_should_only_create_specified_detector_type(self):
|
|
|
|
for det_type in detectors.api_types:
|
|
|
|
with self.subTest(det_type=det_type):
|
|
|
|
with patch.dict(
|
|
|
|
"frigate.detectors.api_types",
|
|
|
|
{det_type: Mock() for det_type in DetectorTypeEnum},
|
|
|
|
):
|
|
|
|
test_cfg = parse_obj_as(
|
|
|
|
DetectorConfig, ({"type": det_type, "model": {}})
|
|
|
|
)
|
|
|
|
test_cfg.model.path = "/test/modelpath"
|
|
|
|
test_obj = frigate.object_detection.LocalObjectDetector(
|
|
|
|
detector_config=test_cfg
|
|
|
|
)
|
|
|
|
|
|
|
|
assert test_obj is not None
|
|
|
|
for api_key, mock_detector in detectors.api_types.items():
|
|
|
|
if test_cfg.type == api_key:
|
|
|
|
mock_detector.assert_called_once_with(test_cfg)
|
|
|
|
else:
|
|
|
|
mock_detector.assert_not_called()
|
|
|
|
|
|
|
|
@patch.dict(
|
|
|
|
"frigate.detectors.api_types",
|
|
|
|
{det_type: Mock() for det_type in DetectorTypeEnum},
|
|
|
|
)
|
|
|
|
def test_detect_raw_given_tensor_input_should_return_api_detect_raw_result(self):
|
|
|
|
mock_cputfl = detectors.api_types[DetectorTypeEnum.cpu]
|
2022-11-04 03:23:09 +01:00
|
|
|
|
|
|
|
TEST_DATA = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
|
|
|
|
TEST_DETECT_RESULT = np.ndarray([1, 2, 4, 8, 16, 32])
|
|
|
|
test_obj_detect = frigate.object_detection.LocalObjectDetector(
|
2022-12-15 14:12:52 +01:00
|
|
|
detector_config=parse_obj_as(DetectorConfig, {"type": "cpu", "model": {}})
|
2022-11-04 03:23:09 +01:00
|
|
|
)
|
|
|
|
|
|
|
|
mock_det_api = mock_cputfl.return_value
|
|
|
|
mock_det_api.detect_raw.return_value = TEST_DETECT_RESULT
|
|
|
|
|
|
|
|
test_result = test_obj_detect.detect_raw(TEST_DATA)
|
|
|
|
|
|
|
|
mock_det_api.detect_raw.assert_called_once_with(tensor_input=TEST_DATA)
|
|
|
|
assert test_result is mock_det_api.detect_raw.return_value
|
|
|
|
|
2022-12-15 14:12:52 +01:00
|
|
|
@patch.dict(
|
|
|
|
"frigate.detectors.api_types",
|
|
|
|
{det_type: Mock() for det_type in DetectorTypeEnum},
|
|
|
|
)
|
2022-11-04 03:23:09 +01:00
|
|
|
def test_detect_raw_given_tensor_input_should_call_api_detect_raw_with_transposed_tensor(
|
2022-12-15 14:12:52 +01:00
|
|
|
self,
|
2022-11-04 03:23:09 +01:00
|
|
|
):
|
2022-12-15 14:12:52 +01:00
|
|
|
mock_cputfl = detectors.api_types[DetectorTypeEnum.cpu]
|
|
|
|
|
2022-11-04 03:23:09 +01:00
|
|
|
TEST_DATA = np.zeros((1, 32, 32, 3), np.uint8)
|
|
|
|
TEST_DETECT_RESULT = np.ndarray([1, 2, 4, 8, 16, 32])
|
|
|
|
|
2022-12-15 14:12:52 +01:00
|
|
|
test_cfg = parse_obj_as(DetectorConfig, {"type": "cpu", "model": {}})
|
|
|
|
test_cfg.model.input_tensor = InputTensorEnum.nchw
|
2022-11-04 03:23:09 +01:00
|
|
|
|
|
|
|
test_obj_detect = frigate.object_detection.LocalObjectDetector(
|
2022-12-15 14:12:52 +01:00
|
|
|
detector_config=test_cfg
|
2022-11-04 03:23:09 +01:00
|
|
|
)
|
|
|
|
|
|
|
|
mock_det_api = mock_cputfl.return_value
|
|
|
|
mock_det_api.detect_raw.return_value = TEST_DETECT_RESULT
|
|
|
|
|
|
|
|
test_result = test_obj_detect.detect_raw(TEST_DATA)
|
|
|
|
|
|
|
|
mock_det_api.detect_raw.assert_called_once()
|
|
|
|
assert (
|
|
|
|
mock_det_api.detect_raw.call_args.kwargs["tensor_input"].shape
|
|
|
|
== np.zeros((1, 3, 32, 32)).shape
|
|
|
|
)
|
|
|
|
|
|
|
|
assert test_result is mock_det_api.detect_raw.return_value
|
|
|
|
|
2022-12-15 14:12:52 +01:00
|
|
|
@patch.dict(
|
|
|
|
"frigate.detectors.api_types",
|
|
|
|
{det_type: Mock() for det_type in DetectorTypeEnum},
|
|
|
|
)
|
2022-11-04 03:23:09 +01:00
|
|
|
@patch("frigate.object_detection.load_labels")
|
|
|
|
def test_detect_given_tensor_input_should_return_lfiltered_detections(
|
2022-12-15 14:12:52 +01:00
|
|
|
self, mock_load_labels
|
2022-11-04 03:23:09 +01:00
|
|
|
):
|
2022-12-15 14:12:52 +01:00
|
|
|
mock_cputfl = detectors.api_types[DetectorTypeEnum.cpu]
|
|
|
|
|
2022-11-04 03:23:09 +01:00
|
|
|
TEST_DATA = np.zeros((1, 32, 32, 3), np.uint8)
|
|
|
|
TEST_DETECT_RAW = [
|
|
|
|
[2, 0.9, 5, 4, 3, 2],
|
|
|
|
[1, 0.5, 8, 7, 6, 5],
|
|
|
|
[0, 0.4, 2, 4, 8, 16],
|
|
|
|
]
|
|
|
|
TEST_DETECT_RESULT = [
|
|
|
|
("label-3", 0.9, (5, 4, 3, 2)),
|
|
|
|
("label-2", 0.5, (8, 7, 6, 5)),
|
|
|
|
]
|
|
|
|
TEST_LABEL_FILE = "/test_labels.txt"
|
|
|
|
mock_load_labels.return_value = [
|
|
|
|
"label-1",
|
|
|
|
"label-2",
|
|
|
|
"label-3",
|
|
|
|
"label-4",
|
|
|
|
"label-5",
|
|
|
|
]
|
|
|
|
|
2022-12-15 14:12:52 +01:00
|
|
|
test_cfg = parse_obj_as(DetectorConfig, {"type": "cpu", "model": {}})
|
|
|
|
test_cfg.model = ModelConfig()
|
2022-11-04 03:23:09 +01:00
|
|
|
test_obj_detect = frigate.object_detection.LocalObjectDetector(
|
2022-12-15 14:12:52 +01:00
|
|
|
detector_config=test_cfg,
|
2022-11-04 03:23:09 +01:00
|
|
|
labels=TEST_LABEL_FILE,
|
|
|
|
)
|
|
|
|
|
|
|
|
mock_load_labels.assert_called_once_with(TEST_LABEL_FILE)
|
|
|
|
|
|
|
|
mock_det_api = mock_cputfl.return_value
|
|
|
|
mock_det_api.detect_raw.return_value = TEST_DETECT_RAW
|
|
|
|
|
|
|
|
test_result = test_obj_detect.detect(tensor_input=TEST_DATA, threshold=0.5)
|
|
|
|
|
|
|
|
mock_det_api.detect_raw.assert_called_once()
|
|
|
|
assert (
|
|
|
|
mock_det_api.detect_raw.call_args.kwargs["tensor_input"].shape
|
|
|
|
== np.zeros((1, 32, 32, 3)).shape
|
|
|
|
)
|
|
|
|
assert test_result == TEST_DETECT_RESULT
|