Refactor inference and AI configuration handling

- Updated the `Inference` class to replace the `get_onnx_engine_bytes` method with `download_model`, allowing for dynamic model loading based on a specified filename.
- Modified the `convert_and_upload_model` method to accept `source_bytes` instead of `onnx_engine_bytes`, enhancing flexibility in model conversion.
- Introduced a new property `engine_name` to the `Inference` class for better access to engine details.
- Adjusted the `AIRecognitionConfig` structure to include a new method pointer `from_dict`, improving configuration handling.
- Updated various test cases to reflect changes in model paths and timeout settings, ensuring consistency and reliability in testing.
This commit is contained in:
Oleksandr Bezdieniezhnykh
2026-03-30 00:22:56 +03:00
parent 6269a7485c
commit 27f4aceb52
25 changed files with 40974 additions and 6172 deletions
+30 -10
View File
@@ -50,20 +50,26 @@ cdef class Inference:
def is_engine_ready(self):
return self.engine is not None
@property
def engine_name(self):
if self.engine is not None:
return self.engine.engine_name
return None
cdef bytes get_onnx_engine_bytes(self):
cdef bytes download_model(self, str filename):
models_dir = constants_inf.MODELS_FOLDER
self.ai_availability_status.set_status(AIAvailabilityEnum.DOWNLOADING)
res = self.loader_client.load_big_small_resource(constants_inf.AI_ONNX_MODEL_FILE, models_dir)
res = self.loader_client.load_big_small_resource(filename, models_dir)
if res.err is not None:
raise Exception(res.err)
return res.data
cdef convert_and_upload_model(self, bytes onnx_engine_bytes, str engine_filename):
cdef convert_and_upload_model(self, bytes source_bytes, str engine_filename):
try:
self.ai_availability_status.set_status(AIAvailabilityEnum.CONVERTING)
models_dir = constants_inf.MODELS_FOLDER
model_bytes = EngineClass.convert_from_onnx(onnx_engine_bytes)
model_bytes = EngineClass.convert_from_source(source_bytes)
self.ai_availability_status.set_status(AIAvailabilityEnum.UPLOADING)
res = self.loader_client.upload_big_small_resource(model_bytes, engine_filename, models_dir)
@@ -108,16 +114,20 @@ cdef class Inference:
self.engine = EngineClass(res.data)
self.ai_availability_status.set_status(AIAvailabilityEnum.ENABLED)
except Exception as e:
source_filename = EngineClass.get_source_filename()
if source_filename is None:
self.ai_availability_status.set_status(AIAvailabilityEnum.ERROR, <str>f"Pre-built engine not found: {str(e)}")
return
self.ai_availability_status.set_status(AIAvailabilityEnum.WARNING, <str>str(e))
onnx_engine_bytes = self.get_onnx_engine_bytes()
source_bytes = self.download_model(source_filename)
self.is_building_engine = True
thread = Thread(target=self.convert_and_upload_model, args=(onnx_engine_bytes, engine_filename))
thread = Thread(target=self.convert_and_upload_model, args=(source_bytes, engine_filename))
thread.daemon = True
thread.start()
return
else:
self.engine = EngineClass(<bytes>self.get_onnx_engine_bytes())
self.engine = EngineClass(<bytes>self.download_model(constants_inf.AI_ONNX_MODEL_FILE))
self.ai_availability_status.set_status(AIAvailabilityEnum.ENABLED)
self.is_building_engine = False
@@ -253,9 +263,19 @@ cdef class Inference:
input_blob = self.preprocess(frames)
outputs = self.engine.run(input_blob)
list_detections = self.postprocess(outputs, ai_config)
if list_detections:
return list_detections[0]
return []
if not list_detections:
return []
cdef list[Detection] detections = list_detections[0]
if ai_config.focal_length > 0 and ai_config.sensor_width > 0:
img_h, img_w = frame.shape[0], frame.shape[1]
gsd = ai_config.sensor_width * ai_config.altitude / (ai_config.focal_length * img_w)
detections = [
d for d in detections
if d.w * img_w * gsd <= constants_inf.annotations_dict[d.cls].max_object_size_meters
and d.h * img_h * gsd <= constants_inf.annotations_dict[d.cls].max_object_size_meters
]
return detections
cdef _process_video(self, AIRecognitionConfig ai_config, str video_name):
cdef int frame_count = 0