Pabloler21 Claude Opus 5.5 commited on
Commit
c96fcf1
·
1 Parent(s): 94d00f7

Alinear el umbral de ByteTrack para no perder personas detectadas

Browse files

ByteTrack solo crea seguimientos nuevos con detecciones de confianza
>= high_conf_det_threshold (0.6 por defecto), así que las personas
detectadas con 0.4-0.6 nunca recibían número y no se mostraban: en el
video de ejemplo se perdía el 31% de las detecciones (ahora se muestra
el 95%, y se siguen 48 personas distintas en vez de 31). Se alinea con
CONF y la creación del tracker pasa a new_bytetrack() para probarla
sin cargar el modelo.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

Files changed (2) hide show
  1. camguard/detection.py +22 -5
  2. tests/test_detection.py +29 -0
camguard/detection.py CHANGED
@@ -27,6 +27,27 @@ def load_model():
27
  return RFDETRSmall()
28
 
29
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
30
  class PersonTracker:
31
  """Detecta personas en cada cuadro y les asigna un número de seguimiento estable.
32
 
@@ -41,11 +62,7 @@ class PersonTracker:
41
  def __init__(self, fps: float, conf: float = CONF):
42
  self._model = load_model()
43
  self._conf = conf
44
- # El umbral de activación por defecto (0.7) tardaría en "confirmar" a las personas,
45
- # y minimum_consecutive_frames=1 les da número desde el primer cuadro en que aparecen.
46
- self._tracker = ByteTrackTracker(
47
- frame_rate=fps, track_activation_threshold=conf, minimum_consecutive_frames=1
48
- )
49
 
50
  def update(self, frame_bgr: np.ndarray) -> sv.Detections:
51
  """Procesa el siguiente cuadro del video.
 
27
  return RFDETRSmall()
28
 
29
 
30
+ def new_bytetrack(fps: float, conf: float = CONF) -> ByteTrackTracker:
31
+ """Crea el tracker ByteTrack configurado para la demo.
32
+
33
+ Args:
34
+ fps: Cuadros por segundo que va a recibir (los analizados, no los del archivo). ByteTrack
35
+ lo usa para saber cuánto tiempo "recordar" a una persona que dejó de verse.
36
+ conf: Confianza mínima para empezar a seguir a una persona.
37
+ """
38
+ # ByteTrack trae dos umbrales propios más exigentes que CONF: el de activación (0.7) y el de
39
+ # "detección de alta confianza" (0.6), que es el único que puede crear un seguimiento nuevo.
40
+ # Si no se alinean con CONF, una persona detectada con 0.4-0.6 nunca recibe número y no se
41
+ # muestra (en el video de ejemplo se perdía el 31% de las detecciones).
42
+ # minimum_consecutive_frames=1 les da número desde el primer cuadro en que aparecen.
43
+ return ByteTrackTracker(
44
+ frame_rate=fps,
45
+ track_activation_threshold=conf,
46
+ high_conf_det_threshold=conf,
47
+ minimum_consecutive_frames=1,
48
+ )
49
+
50
+
51
  class PersonTracker:
52
  """Detecta personas en cada cuadro y les asigna un número de seguimiento estable.
53
 
 
62
  def __init__(self, fps: float, conf: float = CONF):
63
  self._model = load_model()
64
  self._conf = conf
65
+ self._tracker = new_bytetrack(fps, conf)
 
 
 
 
66
 
67
  def update(self, frame_bgr: np.ndarray) -> sv.Detections:
68
  """Procesa el siguiente cuadro del video.
tests/test_detection.py ADDED
@@ -0,0 +1,29 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import numpy as np
2
+ import supervision as sv
3
+
4
+ from camguard.config import PERSON_ID
5
+ from camguard.detection import new_bytetrack
6
+
7
+
8
+ def person(confidence):
9
+ return sv.Detections(
10
+ xyxy=np.array([[10.0, 10.0, 30.0, 60.0]]),
11
+ confidence=np.array([confidence]),
12
+ class_id=np.array([PERSON_ID]),
13
+ )
14
+
15
+
16
+ def test_tracks_people_with_confidence_between_conf_and_06():
17
+ # ByteTrack trae un umbral interno (0.6) para crear seguimientos: si no se alinea con CONF,
18
+ # una persona detectada con 0.5 nunca recibe número y no aparece (se perdía ~31%).
19
+ tracker = new_bytetrack(fps=5, conf=0.4)
20
+ for _ in range(3):
21
+ tracked = tracker.update(person(0.5))
22
+ assert tracked.tracker_id.tolist() != [-1]
23
+
24
+
25
+ def test_ignores_people_below_conf():
26
+ tracker = new_bytetrack(fps=5, conf=0.4)
27
+ for _ in range(3):
28
+ tracked = tracker.update(person(0.3))
29
+ assert all(tid == -1 for tid in tracked.tracker_id)