1javid commited on
Commit
cd04a2e
·
verified ·
1 Parent(s): 993196a

Upload 3 files

Browse files
Files changed (2) hide show
  1. app.py +5 -5
  2. object_distance.py +47 -14
app.py CHANGED
@@ -14,6 +14,7 @@ from object_distance import (
14
  estimate_distances,
15
  estimate_focal_length,
16
  load_yolo,
 
17
  run_yolo,
18
  )
19
 
@@ -120,7 +121,7 @@ def run_object_distance_task(
120
  inner_ratio: float,
121
  min_depth_value: float,
122
  blend_weight_pinhole: float,
123
- ) -> Tuple[np.ndarray, np.ndarray, pd.DataFrame, Dict[str, Any]]:
124
  img_bgr = _ensure_bgr(image_rgb)
125
 
126
  if focal_mode == "Estimate from FOV":
@@ -154,7 +155,6 @@ def run_object_distance_task(
154
  depth_heatmap = depth_to_heatmap(depth_map)
155
  det_df = _detections_df(detections)
156
 
157
- # Add some run metadata for convenience
158
  metrics = dict(metrics)
159
  metrics.update(
160
  {
@@ -165,8 +165,8 @@ def run_object_distance_task(
165
  "focal_length_px": float(focal_length),
166
  }
167
  )
168
-
169
- return _bgr_to_rgb(annotated), _bgr_to_rgb(depth_heatmap), det_df, metrics
170
 
171
 
172
  DESCRIPTION = """
@@ -244,7 +244,7 @@ with gr.Blocks(title="CV Project Playground", analytics_enabled=False) as demo:
244
  out_depth = gr.Image(label="MiDaS depth heatmap", type="numpy")
245
 
246
  out_table = gr.Dataframe(label="Detections table", wrap=True)
247
- out_metrics = gr.JSON(label="Evaluation / run metrics")
248
 
249
  run_btn_2.click(
250
  fn=run_object_distance_task,
 
14
  estimate_distances,
15
  estimate_focal_length,
16
  load_yolo,
17
+ metrics_table,
18
  run_yolo,
19
  )
20
 
 
121
  inner_ratio: float,
122
  min_depth_value: float,
123
  blend_weight_pinhole: float,
124
+ ) -> Tuple[np.ndarray, np.ndarray, pd.DataFrame, pd.DataFrame]:
125
  img_bgr = _ensure_bgr(image_rgb)
126
 
127
  if focal_mode == "Estimate from FOV":
 
155
  depth_heatmap = depth_to_heatmap(depth_map)
156
  det_df = _detections_df(detections)
157
 
 
158
  metrics = dict(metrics)
159
  metrics.update(
160
  {
 
165
  "focal_length_px": float(focal_length),
166
  }
167
  )
168
+ metrics_df = pd.DataFrame(metrics_table(metrics), columns=["metric", "value"])
169
+ return _bgr_to_rgb(annotated), _bgr_to_rgb(depth_heatmap), det_df, metrics_df
170
 
171
 
172
  DESCRIPTION = """
 
244
  out_depth = gr.Image(label="MiDaS depth heatmap", type="numpy")
245
 
246
  out_table = gr.Dataframe(label="Detections table", wrap=True)
247
+ out_metrics = gr.Dataframe(label="Evaluation metrics (key)", wrap=True)
248
 
249
  run_btn_2.click(
250
  fn=run_object_distance_task,
object_distance.py CHANGED
@@ -465,6 +465,43 @@ def compute_evaluation_metrics(
465
  return metrics
466
 
467
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
468
  def save_evaluation_outputs(
469
  detections: list[dict],
470
  metrics: dict,
@@ -493,9 +530,11 @@ def save_evaluation_outputs(
493
  det.get("method", "unknown"),
494
  ])
495
 
496
- metrics_path = os.path.join(eval_dir, "metrics.json")
497
- with open(metrics_path, "w", encoding="utf-8") as f:
498
- json.dump(metrics, f, indent=2)
 
 
499
 
500
  report_path = os.path.join(eval_dir, "evaluation_report.txt")
501
  with open(report_path, "w", encoding="utf-8") as f:
@@ -504,16 +543,10 @@ def save_evaluation_outputs(
504
  f.write("This report measures internal consistency only.\n")
505
  f.write("No ground-truth object distances are available here, so these metrics\n")
506
  f.write("should be interpreted as coverage / robustness diagnostics, not absolute accuracy.\n\n")
507
- f.write("Key metrics\n")
508
- f.write("-----------\n")
509
- for key, value in metrics.items():
510
- if value is None:
511
- pretty = "N/A"
512
- elif isinstance(value, float):
513
- pretty = f"{value:.4f}"
514
- else:
515
- pretty = str(value)
516
- f.write(f"{key}: {pretty}\n")
517
 
518
  f.write("\nMetric sufficiency note\n")
519
  f.write("----------------------\n")
@@ -522,7 +555,7 @@ def save_evaluation_outputs(
522
  f.write("- To measure real accuracy, add ground-truth distances and report MAE/RMSE/MAPE against labels.\n")
523
 
524
  print(f" Saved -> {csv_path}")
525
- print(f" Saved -> {metrics_path}")
526
  print(f" Saved -> {report_path}")
527
 
528
 
 
465
  return metrics
466
 
467
 
468
+ def metrics_table(metrics: dict) -> list[list[str]]:
469
+ """
470
+ Convert the full metrics dict into a small table (key metrics only).
471
+ Returns rows: [metric_name, value].
472
+ """
473
+ def fmt(v):
474
+ if v is None:
475
+ return "N/A"
476
+ if isinstance(v, float):
477
+ return f"{v:.4f}"
478
+ return str(v)
479
+
480
+ keys = [
481
+ # Coverage
482
+ ("num_detections", "num_detections"),
483
+ ("mean_confidence", "mean_confidence"),
484
+ ("known_height_coverage", "known_height_coverage"),
485
+ ("distance_coverage", "distance_coverage"),
486
+ ("unresolved_count", "unresolved_count"),
487
+ # Calibration
488
+ ("calibration_anchor_count", "calibration_anchor_count"),
489
+ ("midas_scale_factor", "midas_scale_factor"),
490
+ ("anchor_scale_cv", "anchor_scale_cv"),
491
+ # Agreement (if available)
492
+ ("agreement_sample_count", "agreement_sample_count"),
493
+ ("agreement_mae_m", "agreement_mae_m"),
494
+ ("agreement_rmse_m", "agreement_rmse_m"),
495
+ ("agreement_mean_relative_error", "agreement_mean_relative_error"),
496
+ ("agreement_within_20pct", "agreement_within_20pct"),
497
+ ]
498
+
499
+ rows = []
500
+ for label, k in keys:
501
+ rows.append([label, fmt(metrics.get(k))])
502
+ return rows
503
+
504
+
505
  def save_evaluation_outputs(
506
  detections: list[dict],
507
  metrics: dict,
 
530
  det.get("method", "unknown"),
531
  ])
532
 
533
+ metrics_table_path = os.path.join(eval_dir, "metrics_table.csv")
534
+ with open(metrics_table_path, "w", newline="", encoding="utf-8") as f:
535
+ writer = csv.writer(f)
536
+ writer.writerow(["metric", "value"])
537
+ writer.writerows(metrics_table(metrics))
538
 
539
  report_path = os.path.join(eval_dir, "evaluation_report.txt")
540
  with open(report_path, "w", encoding="utf-8") as f:
 
543
  f.write("This report measures internal consistency only.\n")
544
  f.write("No ground-truth object distances are available here, so these metrics\n")
545
  f.write("should be interpreted as coverage / robustness diagnostics, not absolute accuracy.\n\n")
546
+ f.write("Key metrics (table)\n")
547
+ f.write("-------------------\n")
548
+ for k, v in metrics_table(metrics):
549
+ f.write(f"{k}: {v}\n")
 
 
 
 
 
 
550
 
551
  f.write("\nMetric sufficiency note\n")
552
  f.write("----------------------\n")
 
555
  f.write("- To measure real accuracy, add ground-truth distances and report MAE/RMSE/MAPE against labels.\n")
556
 
557
  print(f" Saved -> {csv_path}")
558
+ print(f" Saved -> {metrics_table_path}")
559
  print(f" Saved -> {report_path}")
560
 
561