cyberai-1 commited on
Commit
4d8bdee
·
1 Parent(s): 5532eb5

Update upload

Browse files
Files changed (3) hide show
  1. __pycache__/app.cpython-311.pyc +0 -0
  2. app.py +69 -8
  3. test_csv_format.py +140 -0
__pycache__/app.cpython-311.pyc CHANGED
Binary files a/__pycache__/app.cpython-311.pyc and b/__pycache__/app.cpython-311.pyc differ
 
app.py CHANGED
@@ -82,8 +82,8 @@ def _load_model_background():
82
  _model_ready = True
83
  print("✅ Modèle YOLO chargé !")
84
 
85
- # ── CORRECTION 3 : utiliser yolov8n (plus stable sur HuggingFace Spaces) ─────
86
- def _get_model(key="yolov8n"): # ← WAS "yolo11n" (moins fiable sur HF)
87
  p = MODELS_DIR / f"{key}.pt"
88
  if not p.exists():
89
  m = YOLO(f"{key}.pt")
@@ -248,6 +248,7 @@ def _worker(jid):
248
  print(f"[PROCESS] Starting frame processing...\n")
249
 
250
  frame_count = 0
 
251
 
252
  while True:
253
  ret, frame = cap.read()
@@ -255,6 +256,7 @@ def _worker(jid):
255
  break
256
 
257
  frame_count += 1
 
258
 
259
  # Run inference
260
  results = _model(frame, conf=CONF, iou=IOU, imgsz=INFER_SZ, verbose=False)
@@ -270,8 +272,35 @@ def _worker(jid):
270
  if class_name:
271
  job["detections"][class_name] = job["detections"].get(class_name, 0) + 1
272
 
273
- # Draw bounding box
274
  x1, y1, x2, y2 = map(int, box.xyxy[0])
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
275
  color = CLASS_COLORS.get(class_name, (255, 255, 255))
276
  label = f"{class_name} {conf:.2f}"
277
 
@@ -288,6 +317,9 @@ def _worker(jid):
288
  detections = sum(job['detections'].values())
289
  print(f"[PROCESS] Frame {frame_count}/{total_frames} ({progress:.1f}%) - Detections: {detections}")
290
 
 
 
 
291
  # Release resources
292
  cap.release()
293
  out.release()
@@ -359,11 +391,40 @@ def api_logs_csv(scene_id):
359
 
360
  output = io.StringIO()
361
  writer = csv.writer(output)
362
- writer.writerow(["scene_id", "video_name", "class_name", "count",
363
- "generated_at", "total_frames"])
364
- for class_name, count in job.get("detections", {}).items():
365
- writer.writerow([scene_id, job["name"], class_name, count,
366
- datetime.now().isoformat(), job.get("frames", 0)])
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
367
 
368
  return Response(
369
  output.getvalue(),
 
82
  _model_ready = True
83
  print("✅ Modèle YOLO chargé !")
84
 
85
+ # ── CORRECTION 3 : utiliser yolov11n (plus stable sur HuggingFace Spaces) ─────
86
+ def _get_model(key="yolov11n"): # ← WAS "yolo11n" (moins fiable sur HF)
87
  p = MODELS_DIR / f"{key}.pt"
88
  if not p.exists():
89
  m = YOLO(f"{key}.pt")
 
248
  print(f"[PROCESS] Starting frame processing...\n")
249
 
250
  frame_count = 0
251
+ frame_detections = [] # Store all detections for CSV export
252
 
253
  while True:
254
  ret, frame = cap.read()
 
256
  break
257
 
258
  frame_count += 1
259
+ timestamp_sec = (frame_count - 1) / fps if fps > 0 else 0
260
 
261
  # Run inference
262
  results = _model(frame, conf=CONF, iou=IOU, imgsz=INFER_SZ, verbose=False)
 
272
  if class_name:
273
  job["detections"][class_name] = job["detections"].get(class_name, 0) + 1
274
 
275
+ # Get bounding box coordinates
276
  x1, y1, x2, y2 = map(int, box.xyxy[0])
277
+ cx = (x1 + x2) // 2
278
+ cy = (y1 + y2) // 2
279
+
280
+ # Store detection data for CSV
281
+ frame_detections.append({
282
+ "frame": frame_count,
283
+ "timestamp_sec": timestamp_sec,
284
+ "scene_name": jid,
285
+ "group_id": jid,
286
+ "video_name": job["name"],
287
+ "track_id": "",
288
+ "class_name": class_name,
289
+ "confidence": conf,
290
+ "bbox_x1": x1,
291
+ "bbox_y1": y1,
292
+ "bbox_x2": x2,
293
+ "bbox_y2": y2,
294
+ "cx": cx,
295
+ "cy": cy,
296
+ "frame_width": width,
297
+ "frame_height": height,
298
+ "crossed_line": "false",
299
+ "direction": "",
300
+ "speed_px_s": 0.0
301
+ })
302
+
303
+ # Draw bounding box
304
  color = CLASS_COLORS.get(class_name, (255, 255, 255))
305
  label = f"{class_name} {conf:.2f}"
306
 
 
317
  detections = sum(job['detections'].values())
318
  print(f"[PROCESS] Frame {frame_count}/{total_frames} ({progress:.1f}%) - Detections: {detections}")
319
 
320
+ # Save frame detections for later CSV export
321
+ job["frame_detections"] = frame_detections
322
+
323
  # Release resources
324
  cap.release()
325
  out.release()
 
391
 
392
  output = io.StringIO()
393
  writer = csv.writer(output)
394
+
395
+ # Write CSV header - SCHEMA_EXAMPLE.csv format
396
+ writer.writerow([
397
+ "frame", "timestamp_sec", "scene_name", "group_id",
398
+ "video_name", "track_id", "class_name", "confidence",
399
+ "bbox_x1", "bbox_y1", "bbox_x2", "bbox_y2",
400
+ "cx", "cy", "frame_width", "frame_height",
401
+ "crossed_line", "direction", "speed_px_s"
402
+ ])
403
+
404
+ # Write detections for each frame
405
+ frame_detections = job.get("frame_detections", [])
406
+ for det in frame_detections:
407
+ writer.writerow([
408
+ det["frame"],
409
+ f"{det['timestamp_sec']:.3f}",
410
+ det["scene_name"],
411
+ det["group_id"],
412
+ det["video_name"],
413
+ det["track_id"],
414
+ det["class_name"],
415
+ f"{det['confidence']:.3f}",
416
+ det["bbox_x1"],
417
+ det["bbox_y1"],
418
+ det["bbox_x2"],
419
+ det["bbox_y2"],
420
+ det["cx"],
421
+ det["cy"],
422
+ det["frame_width"],
423
+ det["frame_height"],
424
+ det["crossed_line"],
425
+ det["direction"],
426
+ f"{det['speed_px_s']:.1f}"
427
+ ])
428
 
429
  return Response(
430
  output.getvalue(),
test_csv_format.py ADDED
@@ -0,0 +1,140 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #!/usr/bin/env python3
2
+ """
3
+ Test script to verify CSV format matches SCHEMA_EXAMPLE.csv
4
+ """
5
+
6
+ import csv
7
+ from io import StringIO
8
+
9
+ # Exemple de détections comme generées par le backend
10
+ frame_detections = [
11
+ {
12
+ "frame": 1,
13
+ "timestamp_sec": 0.033,
14
+ "scene_name": "abc123",
15
+ "group_id": "abc123",
16
+ "video_name": "traffic_clip1.mp4",
17
+ "track_id": "",
18
+ "class_name": "Vehicle",
19
+ "confidence": 0.912,
20
+ "bbox_x1": 340,
21
+ "bbox_y1": 210,
22
+ "bbox_x2": 520,
23
+ "bbox_y2": 310,
24
+ "cx": 430,
25
+ "cy": 260,
26
+ "frame_width": 1920,
27
+ "frame_height": 1080,
28
+ "crossed_line": "false",
29
+ "direction": "",
30
+ "speed_px_s": 0.0
31
+ },
32
+ {
33
+ "frame": 2,
34
+ "timestamp_sec": 0.067,
35
+ "scene_name": "abc123",
36
+ "group_id": "abc123",
37
+ "video_name": "traffic_clip1.mp4",
38
+ "track_id": "",
39
+ "class_name": "Vehicle",
40
+ "confidence": 0.908,
41
+ "bbox_x1": 345,
42
+ "bbox_y1": 213,
43
+ "bbox_x2": 525,
44
+ "bbox_y2": 313,
45
+ "cx": 435,
46
+ "cy": 263,
47
+ "frame_width": 1920,
48
+ "frame_height": 1080,
49
+ "crossed_line": "false",
50
+ "direction": "",
51
+ "speed_px_s": 14.2
52
+ },
53
+ {
54
+ "frame": 48,
55
+ "timestamp_sec": 1.600,
56
+ "scene_name": "abc123",
57
+ "group_id": "abc123",
58
+ "video_name": "traffic_clip1.mp4",
59
+ "track_id": "",
60
+ "class_name": "Vehicle",
61
+ "confidence": 0.887,
62
+ "bbox_x1": 560,
63
+ "bbox_y1": 290,
64
+ "bbox_x2": 740,
65
+ "bbox_y2": 390,
66
+ "cx": 650,
67
+ "cy": 340,
68
+ "frame_width": 1920,
69
+ "frame_height": 1080,
70
+ "crossed_line": "true",
71
+ "direction": "down",
72
+ "speed_px_s": 15.1
73
+ },
74
+ ]
75
+
76
+ # Generate CSV
77
+ output = StringIO()
78
+ writer = csv.writer(output)
79
+
80
+ # Header
81
+ writer.writerow([
82
+ "frame", "timestamp_sec", "scene_name", "group_id",
83
+ "video_name", "track_id", "class_name", "confidence",
84
+ "bbox_x1", "bbox_y1", "bbox_x2", "bbox_y2",
85
+ "cx", "cy", "frame_width", "frame_height",
86
+ "crossed_line", "direction", "speed_px_s"
87
+ ])
88
+
89
+ # Data rows
90
+ for det in frame_detections:
91
+ writer.writerow([
92
+ det["frame"],
93
+ f"{det['timestamp_sec']:.3f}",
94
+ det["scene_name"],
95
+ det["group_id"],
96
+ det["video_name"],
97
+ det["track_id"],
98
+ det["class_name"],
99
+ f"{det['confidence']:.3f}",
100
+ det["bbox_x1"],
101
+ det["bbox_y1"],
102
+ det["bbox_x2"],
103
+ det["bbox_y2"],
104
+ det["cx"],
105
+ det["cy"],
106
+ det["frame_width"],
107
+ det["frame_height"],
108
+ det["crossed_line"],
109
+ det["direction"],
110
+ f"{det['speed_px_s']:.1f}"
111
+ ])
112
+
113
+ # Print result
114
+ csv_output = output.getvalue()
115
+ print("Generated CSV:")
116
+ print("=" * 120)
117
+ print(csv_output)
118
+ print("=" * 120)
119
+
120
+ # Compare with expected format
121
+ expected_header = "frame,timestamp_sec,scene_name,group_id,video_name,track_id,class_name,confidence,bbox_x1,bbox_y1,bbox_x2,bbox_y2,cx,cy,frame_width,frame_height,crossed_line,direction,speed_px_s"
122
+ actual_header = csv_output.split('\n')[0]
123
+
124
+ print("\nExpected header:")
125
+ print(expected_header)
126
+ print("\nActual header:")
127
+ print(actual_header)
128
+ print("\nHeaders match:", expected_header == actual_header)
129
+
130
+ # Verify number of columns
131
+ lines = csv_output.strip().split('\n')
132
+ for i, line in enumerate(lines, 1):
133
+ cols = line.split(',')
134
+ expected_cols = 19
135
+ if len(cols) != expected_cols:
136
+ print(f"Row {i}: WARNING - Expected {expected_cols} columns, got {len(cols)}")
137
+ else:
138
+ print(f"Row {i}: OK ({len(cols)} columns)")
139
+
140
+ print("\n✅ CSV Format validation complete!")