add cpu fallback detector

This commit is contained in:
Winston Ametsitsi 2024-03-13 01:01:14 -07:00
parent e46b020395
commit 85ccd1e8f1
4 changed files with 62 additions and 36 deletions

View File

@ -1287,44 +1287,59 @@ class FrigateConfig(FrigateBaseModel):
config.model.check_and_load_plus_model(plus_api)
for key, detector in config.detectors.items():
detector_config: DetectorConfig = parse_obj_as(DetectorConfig, detector)
if detector_config.model is None:
detector_config.model = config.model
else:
model = detector_config.model
schema = ModelConfig.schema()["properties"]
if (
model.width != schema["width"]["default"]
or model.height != schema["height"]["default"]
or model.labelmap_path is not None
or model.labelmap is not {}
or model.input_tensor != schema["input_tensor"]["default"]
or model.input_pixel_format
!= schema["input_pixel_format"]["default"]
):
logger.warning(
"Customizing more than a detector model path is unsupported."
)
merged_model = deep_merge(
detector_config.model.dict(exclude_unset=True),
config.model.dict(exclude_unset=True),
config.detectors[key] = self.generate_detector_config(
config, detector, plus_api
)
if "path" not in merged_model:
if detector_config.type == "cpu":
merged_model["path"] = "/cpu_model.tflite"
elif detector_config.type == "edgetpu":
merged_model["path"] = "/edgetpu_model.tflite"
detector_config.model = ModelConfig.parse_obj(merged_model)
detector_config.model.check_and_load_plus_model(
plus_api, detector_config.type
)
detector_config.model.compute_model_hash()
config.detectors[key] = detector_config
return config
def generate_detector_config(self, config: FrigateConfig, detector, plus_api):
detector_config: DetectorConfig = parse_obj_as(DetectorConfig, detector)
if detector_config.model is None:
detector_config.model = config.model
else:
model = detector_config.model
schema = ModelConfig.schema()["properties"]
if (
model.width != schema["width"]["default"]
or model.height != schema["height"]["default"]
or model.labelmap_path is not None
or model.labelmap is not {}
or model.input_tensor != schema["input_tensor"]["default"]
or model.input_pixel_format
!= schema["input_pixel_format"]["default"]
):
logger.warning(
"Customizing more than a detector model path is unsupported."
)
merged_model = deep_merge(
detector_config.model.dict(exclude_unset=True),
config.model.dict(exclude_unset=True),
)
if "path" not in merged_model:
if detector_config.type == "cpu":
merged_model["path"] = "/cpu_model.tflite"
elif detector_config.type == "edgetpu":
merged_model["path"] = "/edgetpu_model.tflite"
detector_config.model = ModelConfig.parse_obj(merged_model)
detector_config.model.check_and_load_plus_model(
plus_api, detector_config.type
)
detector_config.model.compute_model_hash()
if detector_config.type != "cpu":
fallback_config = config.copy(deep=True)
fallback_config.model = ModelConfig()
detector_config.fallback_config = self.generate_detector_config(
fallback_config,
parse_obj_as(DetectorConfig, DEFAULT_DETECTORS["cpu"]),
plus_api,
)
return detector_config
@validator("cameras")
def ensure_zones_and_cameras_have_different_names(cls, v: Dict[str, CameraConfig]):
zones = [zone for camera in v.values() for zone in camera.zones.keys()]

View File

@ -81,6 +81,7 @@ def run_detector(
out_events: dict[str, mp.Event],
avg_speed,
start,
using_fallback_detector,
detector_config,
):
threading.current_thread().name = f"detector:{name}"
@ -99,7 +100,14 @@ def run_detector(
signal.signal(signal.SIGINT, receiveSignal)
frame_manager = SharedMemoryFrameManager()
object_detector = LocalObjectDetector(detector_config=detector_config)
try:
object_detector = LocalObjectDetector(detector_config=detector_config)
except Exception as ex:
logger.error(f"Got exception when initializing detector: {ex}, falling back to CPU detector")
object_detector = LocalObjectDetector(detector_config=detector_config.fallback_config)
using_fallback_detector.value = 1
outputs = {}
for name in out_events.keys():
@ -146,6 +154,7 @@ class ObjectDetectProcess:
self.detection_queue = detection_queue
self.avg_inference_speed = mp.Value("d", 0.01)
self.detection_start = mp.Value("d", 0.0)
self.using_fallback_detector = mp.Value("i", 0)
self.detect_process = None
self.detector_config = detector_config
self.start_or_restart()
@ -176,6 +185,7 @@ class ObjectDetectProcess:
self.out_events,
self.avg_inference_speed,
self.detection_start,
self.using_fallback_detector,
self.detector_config,
),
)

View File

@ -284,6 +284,7 @@ def stats_snapshot(
# issue https://github.com/python/typeshed/issues/8799
# from mypy 0.981 onwards
"pid": pid,
"using_fallback_detector": bool(detector.using_fallback_detector.value),
}
stats["detection_fps"] = round(total_detection_fps, 2)

View File

@ -232,7 +232,7 @@ export default function System() {
<div data-testid="detectors" className="grid grid-cols-1 3xl:grid-cols-3 md:grid-cols-2 gap-4">
{detectorNames.map((detector) => (
<div key={detector} className="dark:bg-gray-800 shadow-md hover:shadow-lg rounded-lg transition-shadow">
<div className="text-lg flex justify-between p-4">{detector}</div>
<div className="text-lg flex justify-between p-4" style={{ color: detectors[detector]['using_fallback_detector'] ? "red" : null}}>{detector}{detectors[detector]['using_fallback_detector'] ? " - CPU FALLBACK MODE" : ""}</div>
<div className="p-2">
<Table className="w-full">
<Thead>