11"""Darknet object detection."""
2+
23from __future__ import annotations
34
45import configparser
89import pwd
910from abc import ABC , abstractmethod
1011from queue import Empty , Queue
11- from typing import Any
12+ from typing import TYPE_CHECKING , Any
1213
1314import cv2
14- import numpy as np
1515import voluptuous as vol
1616
17- from viseron import Viseron
1817from viseron .const import ENV_CUDA_SUPPORTED , ENV_OPENCL_SUPPORTED
1918from viseron .domains import OptionalDomain , RequireDomain , setup_domain
2019from viseron .domains .motion_detector .const import DOMAIN as MOTION_DETECTOR_DOMAIN
6463 DNN_TARGETS ,
6564)
6665
66+ if TYPE_CHECKING :
67+ import numpy as np
68+
69+ from viseron import Viseron
70+
6771LOGGER = logging .getLogger (__name__ )
6872
6973CONFIG_SCHEMA = vol .Schema (
@@ -140,7 +144,7 @@ def setup_domains(vis: Viseron, config: dict[str, Any]) -> None:
140144 """Set up darknet domains."""
141145 config = config [COMPONENT ]
142146
143- for camera_identifier in config [CONFIG_OBJECT_DETECTOR ][CONFIG_CAMERAS ]. keys () :
147+ for camera_identifier in config [CONFIG_OBJECT_DETECTOR ][CONFIG_CAMERAS ]:
144148 setup_domain (
145149 vis ,
146150 COMPONENT ,
@@ -162,6 +166,13 @@ def setup_domains(vis: Viseron, config: dict[str, Any]) -> None:
162166 )
163167
164168
169+ def unload (vis : Viseron ) -> None :
170+ """Unload the darknet component."""
171+ if COMPONENT in vis .data :
172+ vis .data [COMPONENT ].stop ()
173+ del vis .data [COMPONENT ]
174+
175+
165176class LoadDarknetError (ViseronError ):
166177 """Raised when failing to load Darknet network."""
167178
@@ -210,22 +221,26 @@ def model_height(self) -> int:
210221 return self ._model_height
211222
212223 @property
213- def model_res (self ):
224+ def model_res (self ) -> tuple [ int , int ] :
214225 """Return trained model resolution."""
215226 return self .model_width , self .model_height
216227
217228 @abstractmethod
218- def preprocess (self , frame ) :
229+ def preprocess (self , frame : np . ndarray ) -> np . ndarray | bytes :
219230 """Pre process frame before detection."""
220231
221232 @abstractmethod
222233 def detect (self , frame , camera_identifier , result_queue , min_confidence ):
223234 """Perform detection."""
224235
225236 @abstractmethod
226- def post_process (self , detections , camera_resolution ):
237+ def post_process (self , detections , camera_resolution ) -> list [ DetectedObject ] :
227238 """Post process detections."""
228239
240+ @abstractmethod
241+ def stop (self ) -> None :
242+ """Stop Darknet."""
243+
229244
230245class DarknetDNNError (ViseronError ):
231246 """Raised when failing to load Darknet in subprocess."""
@@ -278,7 +293,7 @@ def spawn_subprocess(self) -> RestartablePopen:
278293 stderr = self ._log_pipe ,
279294 )
280295
281- def preprocess (self , frame ) -> np .ndarray :
296+ def preprocess (self , frame : np . ndarray ) -> np .ndarray :
282297 """Pre process frame before detection."""
283298 return cv2 .resize (
284299 frame ,
@@ -315,12 +330,10 @@ def work_output(self, item) -> None:
315330 return
316331 pop_if_full (self ._result_queues [item ["camera_identifier" ]], item )
317332
318- def post_process (self , detections , camera_resolution ):
333+ def post_process (self , detections , camera_resolution ) -> list [ DetectedObject ] :
319334 """Post process detections."""
320335 _detections = []
321- for (label , confidence , box ) in zip (
322- detections [0 ], detections [1 ], detections [2 ]
323- ):
336+ for label , confidence , box in zip (detections [0 ], detections [1 ], detections [2 ]):
324337 _detections .append (
325338 DetectedObject .from_absolute (
326339 self .labels [int (label )],
@@ -354,6 +367,10 @@ def dnn_preferable_target(self) -> int:
354367 return DNN_TARGETS [DNN_OPENCL ]
355368 return DNN_TARGETS [DNN_CPU ]
356369
370+ def stop (self ) -> None :
371+ """Stop Darknet."""
372+ SubProcessWorker .stop (self )
373+
357374
358375class DarknetNative (BaseDarknet , ChildProcessWorker ):
359376 """Darknet object detector interface using native Darknet.
@@ -454,7 +471,7 @@ def detect(
454471 return None
455472 return item ["result" ]
456473
457- def post_process (self , detections , camera_resolution ):
474+ def post_process (self , detections , camera_resolution ) -> list [ DetectedObject ] :
458475 """Post process detections."""
459476 _detections = []
460477 for label , confidence , box in detections :
@@ -493,3 +510,7 @@ def darknet_data_path(self) -> str:
493510 """Return path to Darknet data file."""
494511 homedir = os .path .expanduser (f"~{ pwd .getpwuid (os .geteuid ())[0 ]} " )
495512 return f"{ homedir } /darknet_data.data"
513+
514+ def stop (self ) -> None :
515+ """Stop Darknet."""
516+ ChildProcessWorker .stop (self )
0 commit comments