cesar commited on
Commit
f0b735d
·
verified ·
1 Parent(s): 982fb7b

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +27 -15
app.py CHANGED
@@ -4,31 +4,38 @@ from ultralytics import YOLO
4
 
5
  # ── Config ─────────────────────────────────────────────
6
  MODEL_PATH = "yolov8n.pt" # peso pre-entrenado (clase “person”)
7
- CONF_THRES = 0.3
8
- LINE_RATIO = 0.5 # línea virtual al 50 % de la altura
9
  # ───────────────────────────────────────────────────────
10
 
11
- # carga una sola vez
12
  model = YOLO(MODEL_PATH)
13
 
14
- # estado global
15
  memory, in_count, out_count = {}, 0, 0
16
 
17
 
18
  def count_people(frame_rgb):
19
- """Procesa un frame RGB -> devuelve frame RGB anotado + texto contador."""
 
 
 
20
  global memory, in_count, out_count
21
 
22
  if frame_rgb is None:
23
  return None, ""
24
 
 
25
  frame_bgr = cv2.cvtColor(frame_rgb, cv2.COLOR_RGB2BGR)
26
  h, w = frame_bgr.shape[:2]
27
  line_y = int(h * LINE_RATIO)
28
 
29
- # detección + tracking
30
- results = model.track(frame_bgr, classes=[0], conf=CONF_THRES,
31
- persist=True, verbose=False)
 
 
 
32
 
33
  annotated = frame_bgr.copy()
34
  cv2.line(annotated, (0, line_y), (w, line_y), (0, 255, 255), 2)
@@ -40,9 +47,9 @@ def count_people(frame_rgb):
40
  tid = int(box.id[0]) if box.id is not None else -1
41
 
42
  prev_cy = memory.get(tid, cy)
43
- if prev_cy < line_y <= cy: # entra
44
  in_count += 1
45
- elif prev_cy > line_y >= cy: # sale
46
  out_count += 1
47
  memory[tid] = cy
48
 
@@ -54,16 +61,19 @@ def count_people(frame_rgb):
54
  total = in_count - out_count
55
  label = f"In: {in_count} | Out: {out_count} | Ocupación: {total}"
56
 
 
57
  annotated_rgb = cv2.cvtColor(annotated, cv2.COLOR_BGR2RGB)
58
  return annotated_rgb, label
59
 
60
 
61
  def reset_counts():
 
62
  global memory, in_count, out_count
63
  memory, in_count, out_count = {}, 0, 0
64
  return None, ""
65
 
66
 
 
67
  with gr.Blocks(title="Contador de personas (entrada única)") as demo:
68
  gr.Markdown("# Contador de personas (entrada única)")
69
 
@@ -74,9 +84,11 @@ with gr.Blocks(title="Contador de personas (entrada única)") as demo:
74
 
75
  btn_clear = gr.Button("Limpiar")
76
 
77
- # 💡 la clave: inputs=[cam]
78
- cam.stream(count_people, inputs=[cam], outputs=[out_img, out_lbl])
79
- btn_clear.click(reset_counts, outputs=[out_img, out_lbl])
 
 
 
 
80
 
81
- if __name__ == "__main__":
82
- demo.launch(max_threads=2, max_queue=60) # cola chica para que no se tape
 
4
 
5
  # ── Config ─────────────────────────────────────────────
6
  MODEL_PATH = "yolov8n.pt" # peso pre-entrenado (clase “person”)
7
+ CONF_THRES = 0.30 # confianza mínima
8
+ LINE_RATIO = 0.50 # posición de la línea virtual (50 % de la altura)
9
  # ───────────────────────────────────────────────────────
10
 
11
+ # modelo — se carga una sola vez
12
  model = YOLO(MODEL_PATH)
13
 
14
+ # estado global del contador
15
  memory, in_count, out_count = {}, 0, 0
16
 
17
 
18
  def count_people(frame_rgb):
19
+ """
20
+ ▸ Recibe un frame RGB (numpy) desde la webcam.
21
+ ▸ Devuelve el frame anotado (RGB) y el texto del contador.
22
+ """
23
  global memory, in_count, out_count
24
 
25
  if frame_rgb is None:
26
  return None, ""
27
 
28
+ # ── convertir RGB ➜ BGR (OpenCV/YOLO) ──────────────
29
  frame_bgr = cv2.cvtColor(frame_rgb, cv2.COLOR_RGB2BGR)
30
  h, w = frame_bgr.shape[:2]
31
  line_y = int(h * LINE_RATIO)
32
 
33
+ # ── detección + tracking (ByteTrack interno) ───────
34
+ results = model.track(frame_bgr,
35
+ classes=[0], # solo “person”
36
+ conf=CONF_THRES,
37
+ persist=True,
38
+ verbose=False)
39
 
40
  annotated = frame_bgr.copy()
41
  cv2.line(annotated, (0, line_y), (w, line_y), (0, 255, 255), 2)
 
47
  tid = int(box.id[0]) if box.id is not None else -1
48
 
49
  prev_cy = memory.get(tid, cy)
50
+ if prev_cy < line_y <= cy: # cruza de arriba → abajo (ENTRA)
51
  in_count += 1
52
+ elif prev_cy > line_y >= cy: # cruza de abajo → arriba (SALE)
53
  out_count += 1
54
  memory[tid] = cy
55
 
 
61
  total = in_count - out_count
62
  label = f"In: {in_count} | Out: {out_count} | Ocupación: {total}"
63
 
64
+ # ── devolver en RGB para que Gradio lo muestre bien ─
65
  annotated_rgb = cv2.cvtColor(annotated, cv2.COLOR_BGR2RGB)
66
  return annotated_rgb, label
67
 
68
 
69
  def reset_counts():
70
+ """Resetea contador y memoria."""
71
  global memory, in_count, out_count
72
  memory, in_count, out_count = {}, 0, 0
73
  return None, ""
74
 
75
 
76
+ # ── Interfaz Gradio ────────────────────────────────────
77
  with gr.Blocks(title="Contador de personas (entrada única)") as demo:
78
  gr.Markdown("# Contador de personas (entrada única)")
79
 
 
84
 
85
  btn_clear = gr.Button("Limpiar")
86
 
87
+ # conectar streaming y botón
88
+ cam.stream(fn=count_people, inputs=[cam], outputs=[out_img, out_lbl])
89
+ btn_clear.click(fn=reset_counts, outputs=[out_img, out_lbl])
90
+
91
+ # ── Cola y lanzamiento ─────────────────────────────────
92
+ demo.queue(concurrency_count=2, max_size=60) # 2 hilos, cola máx 60 frames
93
+ demo.launch()
94