Spaces:
Running
Running
fix: issues
Browse files- src/services/ai_manager.py +14 -11
src/services/ai_manager.py
CHANGED
|
@@ -398,11 +398,16 @@ class AIModelManager:
|
|
| 398 |
self, bgr_enhanced: np.ndarray, scale: tuple
|
| 399 |
) -> list:
|
| 400 |
H, W = bgr_enhanced.shape[:2]
|
| 401 |
-
# Preserve aspect ratio
|
| 402 |
-
#
|
| 403 |
-
#
|
| 404 |
-
#
|
| 405 |
-
#
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 406 |
target_max = max(scale[0], scale[1])
|
| 407 |
long_side = max(W, H)
|
| 408 |
if long_side <= target_max:
|
|
@@ -418,18 +423,16 @@ class AIModelManager:
|
|
| 418 |
# input_size must be set inside the lock — setting it outside
|
| 419 |
# is a race condition when two inference threads run concurrently,
|
| 420 |
# causing the wrong scale to be used and faces to be missed.
|
| 421 |
-
|
| 422 |
-
# math matches the image we're feeding it.
|
| 423 |
-
self.face_app.det_model.input_size = (scale_w, scale_h)
|
| 424 |
faces_at_scale = self.face_app.get(bgr_scaled)
|
| 425 |
sx, sy = W / scale_w, H / scale_h
|
| 426 |
for f in faces_at_scale:
|
| 427 |
if sx != 1.0 or sy != 1.0:
|
| 428 |
f.bbox[0] *= sx; f.bbox[1] *= sy
|
| 429 |
f.bbox[2] *= sx; f.bbox[3] *= sy
|
| 430 |
-
|
| 431 |
-
|
| 432 |
-
|
| 433 |
return faces_at_scale
|
| 434 |
except Exception:
|
| 435 |
return []
|
|
|
|
| 398 |
self, bgr_enhanced: np.ndarray, scale: tuple
|
| 399 |
) -> list:
|
| 400 |
H, W = bgr_enhanced.shape[:2]
|
| 401 |
+
# Preserve aspect ratio when downscaling. The previous code clamped each
|
| 402 |
+
# dim independently which squashed wide images (e.g. 4032x1816 → 640x640)
|
| 403 |
+
# and produced distorted face crops whose embeddings would not match the
|
| 404 |
+
# same person shot in a normal aspect ratio.
|
| 405 |
+
#
|
| 406 |
+
# NOTE: We keep `input_size` set to the original square `scale`. InsightFace
|
| 407 |
+
# SCRFD internally letterboxes the image into the input_size canvas while
|
| 408 |
+
# preserving aspect ratio — so feeding a (640, 360) image with input_size
|
| 409 |
+
# (640, 640) results in a properly padded 640x640 detector input. The
|
| 410 |
+
# square input_size also matches the ONNX model's expected shape.
|
| 411 |
target_max = max(scale[0], scale[1])
|
| 412 |
long_side = max(W, H)
|
| 413 |
if long_side <= target_max:
|
|
|
|
| 423 |
# input_size must be set inside the lock — setting it outside
|
| 424 |
# is a race condition when two inference threads run concurrently,
|
| 425 |
# causing the wrong scale to be used and faces to be missed.
|
| 426 |
+
self.face_app.det_model.input_size = scale
|
|
|
|
|
|
|
| 427 |
faces_at_scale = self.face_app.get(bgr_scaled)
|
| 428 |
sx, sy = W / scale_w, H / scale_h
|
| 429 |
for f in faces_at_scale:
|
| 430 |
if sx != 1.0 or sy != 1.0:
|
| 431 |
f.bbox[0] *= sx; f.bbox[1] *= sy
|
| 432 |
f.bbox[2] *= sx; f.bbox[3] *= sy
|
| 433 |
+
if hasattr(f, 'kps') and f.kps is not None:
|
| 434 |
+
f.kps[:, 0] *= sx
|
| 435 |
+
f.kps[:, 1] *= sy
|
| 436 |
return faces_at_scale
|
| 437 |
except Exception:
|
| 438 |
return []
|