Skip GSD and size filtering without altitude

This commit is contained in:
Roman Meshko
2026-04-19 21:50:48 +03:00
parent 7d897df380
commit 5cfcdb5fd5
9 changed files with 54 additions and 11 deletions
+1
View File
@@ -12,6 +12,7 @@ cdef class AIRecognitionConfig:
cdef public int model_batch_size
cdef public bint has_altitude
cdef public double altitude
cdef public double focal_length
cdef public double sensor_width
+4 -3
View File
@@ -25,7 +25,8 @@ cdef class AIRecognitionConfig:
self.big_image_tile_overlap_percent = big_image_tile_overlap_percent
self.altitude = altitude
self.has_altitude = altitude is not None
self.altitude = 0.0 if altitude is None else float(altitude)
self.focal_length = focal_length
self.sensor_width = sensor_width
@@ -36,7 +37,7 @@ cdef class AIRecognitionConfig:
f'frame_period_recognition : {self.frame_period_recognition}, '
f'big_image_tile_overlap_percent: {self.big_image_tile_overlap_percent}, '
f'model_batch_size: {self.model_batch_size}, '
f'altitude: {self.altitude}, '
f'altitude: {self.altitude if self.has_altitude else None}, '
f'focal_length: {self.focal_length}, '
f'sensor_width: {self.sensor_width}'
)
@@ -56,7 +57,7 @@ cdef class AIRecognitionConfig:
data.get("big_image_tile_overlap_percent", 20),
data.get("altitude", 400),
data.get("altitude", None),
data.get("focal_length", 24),
data.get("sensor_width", 23.5)
)
+17 -2
View File
@@ -311,13 +311,22 @@ cdef class Inference:
cdef double ground_sampling_distance
cdef int model_h, model_w
cdef int img_h, img_w
cdef bint has_gsd
model_h, model_w = self.engine.get_input_shape()
img_h, img_w, _ = frame.shape
ground_sampling_distance = ai_config.sensor_width * ai_config.altitude / (ai_config.focal_length * img_w)
constants_inf.log(<str>f'ground sampling distance: {ground_sampling_distance}')
has_gsd = ai_config.has_altitude and ai_config.focal_length > 0 and ai_config.sensor_width > 0 and img_w > 0
ground_sampling_distance = 0.0
if has_gsd:
ground_sampling_distance = ai_config.sensor_width * ai_config.altitude / (ai_config.focal_length * img_w)
constants_inf.log(<str>f'ground sampling distance: {ground_sampling_distance}')
else:
constants_inf.log(<str>'ground sampling distance: skipped (altitude unavailable)')
if img_h <= 1.5 * model_h and img_w <= 1.5 * model_w:
all_frame_data.append((frame, original_media_name, f'{original_media_name}_000000', ground_sampling_distance))
else:
if not has_gsd:
all_frame_data.append((frame, original_media_name, f'{original_media_name}_000000', ground_sampling_distance))
return
tile_size = int(constants_inf.METERS_IN_TILE / ground_sampling_distance)
constants_inf.log(<str> f'calc tile size: {tile_size}')
res = self.split_to_tiles(frame, original_media_name, tile_size, ai_config.big_image_tile_overlap_percent)
@@ -410,6 +419,12 @@ cdef class Inference:
if annotation.detections:
constants_inf.log(<str> f'Initial ann: {annotation}')
if ground_sampling_distance <= 0:
if not annotation.detections:
return <bint>False
constants_inf.log(<str>'Skipping physical-size filtering (ground sampling distance unavailable)')
return <bint>True
cdef list[Detection] valid_detections = []
for det in annotation.detections:
m_w = det.w * img_w * ground_sampling_distance
+1 -1
View File
@@ -163,7 +163,7 @@ class AIConfigDto(BaseModel):
tracking_intersection_threshold: float = 0.6
model_batch_size: int = 8
big_image_tile_overlap_percent: int = 20
altitude: float = 400
altitude: Optional[float] = None
focal_length: float = 24
sensor_width: float = 23.5