aibota01 commited on
Commit
ac14a76
Β·
1 Parent(s): 5a45c18
Files changed (1) hide show
  1. app.py +54 -64
app.py CHANGED
@@ -19,14 +19,14 @@ def compute_iou(row):
19
  yA = max(row["ymin_gt"], row["ymin_pred"])
20
  xB = min(row["xmax_gt"], row["xmax_pred"])
21
  yB = min(row["ymax_gt"], row["ymax_pred"])
22
-
23
  inter_width = max(0, xB - xA)
24
  inter_height = max(0, yB - yA)
25
  inter_area = inter_width * inter_height
26
-
27
  boxA_area = (row["xmax_gt"] - row["xmin_gt"]) * (row["ymax_gt"] - row["ymin_gt"])
28
  boxB_area = (row["xmax_pred"] - row["xmin_pred"]) * (row["ymax_pred"] - row["ymin_pred"])
29
-
30
  union_area = boxA_area + boxB_area - inter_area
31
  iou = inter_area / union_area if union_area > 0 else 0
32
  return iou
@@ -34,8 +34,8 @@ def compute_iou(row):
34
  def evaluate_submission(file, submission_name, model_description):
35
  """
36
  Evaluate the submitted CSV file by comparing predicted bounding box coordinates and food weight
37
- against the ground truth. Rows with a weight value of -1 in either ground truth or submission
38
- are filtered out.
39
  """
40
  if file is None:
41
  return "❌ Please upload a file."
@@ -46,8 +46,8 @@ def evaluate_submission(file, submission_name, model_description):
46
  print("Submitted columns:", submission_df.columns.tolist())
47
  except Exception as e:
48
  return f"❌ File read failed: {e}"
49
-
50
- # Load hidden ground truth CSV from a private dataset.
51
  try:
52
  gt_path = hf_hub_download(
53
  repo_id="issai/ground-truth-food-eval",
@@ -58,74 +58,61 @@ def evaluate_submission(file, submission_name, model_description):
58
  gt_df = pd.read_csv(gt_path)
59
  except Exception as e:
60
  return "Error loading ground truth file: " + str(e)
61
-
62
- # --- Debug: Print shapes and samples from both DataFrames ---
63
  print("Ground truth shape:", gt_df.shape)
64
  print("Ground truth sample:")
65
  print(gt_df.head())
66
-
67
  print("Submission shape:", submission_df.shape)
68
  print("Submission sample:")
69
  print(submission_df.head())
70
- # ---------------------------------------------------------
71
-
72
- # Merge on 'image_id'
73
  try:
74
- df = pd.merge(gt_df, submission_df, on="image_id", suffixes=("_gt", "_pred"))
 
 
 
 
75
  except Exception as e:
76
  return f"❌ Error during merge: {e}"
77
-
78
  print(f"βœ… Received {len(submission_df)} predictions for evaluation!")
79
  print("Merged shape:", df.shape)
80
-
81
  if df.empty:
82
- return "No matching image_ids found between ground truth and submission."
83
-
84
  print("Merged columns:", df.columns.tolist())
85
  print("Merged sample data:")
86
- print(df[["image_id", "xmin_gt", "xmin_pred", "weight_gt", "weight_pred"]].head())
87
-
88
- # For further debugging: compute differences for one coordinate and weight.
89
  df["diff_xmin"] = abs(df["xmin_gt"] - df["xmin_pred"])
90
  df["diff_weight"] = abs(df["weight_gt"] - df["weight_pred"])
91
  print("Differences in 'xmin' (head):", df["diff_xmin"].head())
92
  print("Differences in 'weight' (head):", df["diff_weight"].head())
93
 
94
- # Find rows where either diff_xmin or diff_weight is not zero.
95
- nonzero_diff = df[(df["diff_xmin"] != 0) | (df["diff_weight"] != 0)]
96
- if not nonzero_diff.empty:
97
- print("Rows with nonzero differences:")
98
- print(nonzero_diff)
99
- else:
100
- print("No nonzero differences found.")
101
-
102
- # Convert coordinate and weight columns to numeric.
103
- coord_cols = ["xmin_gt", "ymin_gt", "xmax_gt", "ymax_gt",
104
- "xmin_pred", "ymin_pred", "xmax_pred", "ymax_pred"]
105
  for col in coord_cols:
106
  df[col] = pd.to_numeric(df[col], errors="coerce")
 
107
  df["weight_gt"] = pd.to_numeric(df["weight_gt"], errors="coerce")
108
  df["weight_pred"] = pd.to_numeric(df["weight_pred"], errors="coerce")
109
-
110
- # Filter out rows where either weight is -1 ---
111
- num_before = df.shape[0]
112
- df = df[(df["weight_gt"] != -1) & (df["weight_pred"] != -1)]
113
- num_filtered = num_before - df.shape[0]
114
- print(f"Filtered out {num_filtered} rows due to weight == -1")
115
-
116
- if df.empty:
117
- return "No evaluable rows remain after filtering rows with weight == -1."
118
-
119
- # Compute IoU for each row.
120
  df["iou"] = df.apply(compute_iou, axis=1)
121
-
122
- # Compute mean absolute error for food weight predictions.
123
  mean_weight_error = mean_absolute_error(df["weight_gt"], df["weight_pred"])
124
-
125
- # Calculate mean IoU.
126
  mean_iou = df["iou"].mean()
127
-
128
- # Save the evaluation result to the leaderboard.
129
  result = {
130
  "submission_name": submission_name,
131
  "model_description": model_description,
@@ -133,7 +120,7 @@ def evaluate_submission(file, submission_name, model_description):
133
  "mean_weight_error": mean_weight_error,
134
  }
135
  save_submission_result(result)
136
-
137
  result_text = (
138
  f"**Evaluation Results for '{submission_name}'**\n\n"
139
  f"- Model: {model_description}\n"
@@ -148,9 +135,6 @@ LEADERBOARD_FILE = "evaluation_results.csv"
148
  LEADERBOARD_COLUMNS = ["submission_name", "model_description", "mean_iou", "mean_weight_error"]
149
 
150
  def save_submission_result(result):
151
- """
152
- Save a new submission result into the leaderboard CSV.
153
- """
154
  if os.path.exists(LEADERBOARD_FILE):
155
  df = pd.read_csv(LEADERBOARD_FILE)
156
  df = pd.concat([df, pd.DataFrame([result])], ignore_index=True)
@@ -159,9 +143,6 @@ def save_submission_result(result):
159
  df.to_csv(LEADERBOARD_FILE, index=False)
160
 
161
  def load_leaderboard():
162
- """
163
- Load and sort the leaderboard dataframe.
164
- """
165
  if os.path.exists(LEADERBOARD_FILE):
166
  df = pd.read_csv(LEADERBOARD_FILE)
167
  df = df.sort_values(by="mean_weight_error", ascending=True)
@@ -178,27 +159,36 @@ def evaluate_and_refresh(file, submission_name, model_description):
178
 
179
  with gr.Blocks() as demo:
180
  gr.Markdown("# Benchmark Leaderboard: Food Object Detection & Food Weight Prediction")
181
- gr.Markdown("This leaderboard evaluates CSV submissions based on bounding box detection (IoU) and food weight predictions (grams).")
182
-
 
 
 
183
  with gr.Tabs():
184
  with gr.TabItem("πŸ… Leaderboard"):
185
  leaderboard_output = gr.Dataframe(label="Leaderboard")
186
  demo.load(load_leaderboard, outputs=leaderboard_output)
187
  refresh_button = gr.Button("Refresh Leaderboard")
 
188
  def refresh_leaderboard():
189
  return load_leaderboard()
 
190
  refresh_button.click(refresh_leaderboard, outputs=leaderboard_output)
191
-
192
  with gr.TabItem("πŸš€ Submit CSV"):
193
- gr.Markdown("**Submit your predictions CSV file.** The CSV must have the following columns:\n\n"
194
- "`image_id, xmin, ymin, xmax, ymax, weight`")
195
-
196
- submission_file = gr.File(label="Upload Submission CSV", file_types=[".csv"])
 
 
 
 
197
  submission_name_textbox = gr.Textbox(label="Submission Name / Your Name")
198
  model_description_textbox = gr.Textbox(label="Model Description / Model Name")
199
  submit_button = gr.Button("Evaluate Submission")
200
  evaluation_output = gr.Markdown()
201
-
202
  submit_button.click(
203
  evaluate_and_refresh,
204
  inputs=[submission_file, submission_name_textbox, model_description_textbox],
 
19
  yA = max(row["ymin_gt"], row["ymin_pred"])
20
  xB = min(row["xmax_gt"], row["xmax_pred"])
21
  yB = min(row["ymax_gt"], row["ymax_pred"])
22
+
23
  inter_width = max(0, xB - xA)
24
  inter_height = max(0, yB - yA)
25
  inter_area = inter_width * inter_height
26
+
27
  boxA_area = (row["xmax_gt"] - row["xmin_gt"]) * (row["ymax_gt"] - row["ymin_gt"])
28
  boxB_area = (row["xmax_pred"] - row["xmin_pred"]) * (row["ymax_pred"] - row["ymin_pred"])
29
+
30
  union_area = boxA_area + boxB_area - inter_area
31
  iou = inter_area / union_area if union_area > 0 else 0
32
  return iou
 
34
  def evaluate_submission(file, submission_name, model_description):
35
  """
36
  Evaluate the submitted CSV file by comparing predicted bounding box coordinates and food weight
37
+ against the ground truth. We merge on both 'image_name' and 'class_id', because there can be
38
+ multiple items (classes) in the same image.
39
  """
40
  if file is None:
41
  return "❌ Please upload a file."
 
46
  print("Submitted columns:", submission_df.columns.tolist())
47
  except Exception as e:
48
  return f"❌ File read failed: {e}"
49
+
50
+ # Load hidden ground truth CSV from a private dataset (adjust repo_id as needed).
51
  try:
52
  gt_path = hf_hub_download(
53
  repo_id="issai/ground-truth-food-eval",
 
58
  gt_df = pd.read_csv(gt_path)
59
  except Exception as e:
60
  return "Error loading ground truth file: " + str(e)
61
+
62
+ # Debug: Print shapes and first few rows.
63
  print("Ground truth shape:", gt_df.shape)
64
  print("Ground truth sample:")
65
  print(gt_df.head())
66
+
67
  print("Submission shape:", submission_df.shape)
68
  print("Submission sample:")
69
  print(submission_df.head())
70
+
71
+ # Merge on 'image_name' and 'class_id' so that multiple classes per image match up correctly.
 
72
  try:
73
+ df = pd.merge(
74
+ gt_df, submission_df,
75
+ on=["image_name", "class_id"],
76
+ suffixes=("_gt", "_pred")
77
+ )
78
  except Exception as e:
79
  return f"❌ Error during merge: {e}"
80
+
81
  print(f"βœ… Received {len(submission_df)} predictions for evaluation!")
82
  print("Merged shape:", df.shape)
83
+
84
  if df.empty:
85
+ return "No matching rows found between ground truth and submission (image_name/class_id)."
86
+
87
  print("Merged columns:", df.columns.tolist())
88
  print("Merged sample data:")
89
+ print(df[["image_name", "class_id", "xmin_gt", "xmin_pred", "weight_gt", "weight_pred"]].head())
90
+
91
+ # Debug differences in xmin and weight
92
  df["diff_xmin"] = abs(df["xmin_gt"] - df["xmin_pred"])
93
  df["diff_weight"] = abs(df["weight_gt"] - df["weight_pred"])
94
  print("Differences in 'xmin' (head):", df["diff_xmin"].head())
95
  print("Differences in 'weight' (head):", df["diff_weight"].head())
96
 
97
+ # Convert columns to numeric
98
+ coord_cols = [
99
+ "xmin_gt", "ymin_gt", "xmax_gt", "ymax_gt",
100
+ "xmin_pred", "ymin_pred", "xmax_pred", "ymax_pred"
101
+ ]
 
 
 
 
 
 
102
  for col in coord_cols:
103
  df[col] = pd.to_numeric(df[col], errors="coerce")
104
+
105
  df["weight_gt"] = pd.to_numeric(df["weight_gt"], errors="coerce")
106
  df["weight_pred"] = pd.to_numeric(df["weight_pred"], errors="coerce")
107
+
108
+ # Compute IoU for each row
 
 
 
 
 
 
 
 
 
109
  df["iou"] = df.apply(compute_iou, axis=1)
110
+
111
+ # Compute mean absolute error for weight
112
  mean_weight_error = mean_absolute_error(df["weight_gt"], df["weight_pred"])
 
 
113
  mean_iou = df["iou"].mean()
114
+
115
+ # Save the evaluation result to the leaderboard
116
  result = {
117
  "submission_name": submission_name,
118
  "model_description": model_description,
 
120
  "mean_weight_error": mean_weight_error,
121
  }
122
  save_submission_result(result)
123
+
124
  result_text = (
125
  f"**Evaluation Results for '{submission_name}'**\n\n"
126
  f"- Model: {model_description}\n"
 
135
  LEADERBOARD_COLUMNS = ["submission_name", "model_description", "mean_iou", "mean_weight_error"]
136
 
137
  def save_submission_result(result):
 
 
 
138
  if os.path.exists(LEADERBOARD_FILE):
139
  df = pd.read_csv(LEADERBOARD_FILE)
140
  df = pd.concat([df, pd.DataFrame([result])], ignore_index=True)
 
143
  df.to_csv(LEADERBOARD_FILE, index=False)
144
 
145
  def load_leaderboard():
 
 
 
146
  if os.path.exists(LEADERBOARD_FILE):
147
  df = pd.read_csv(LEADERBOARD_FILE)
148
  df = df.sort_values(by="mean_weight_error", ascending=True)
 
159
 
160
  with gr.Blocks() as demo:
161
  gr.Markdown("# Benchmark Leaderboard: Food Object Detection & Food Weight Prediction")
162
+ gr.Markdown(
163
+ "This leaderboard evaluates CSV submissions based on bounding boxes (IoU) "
164
+ "and food weight (grams). **Now merging on image_name + class_id** to handle multiple items."
165
+ )
166
+
167
  with gr.Tabs():
168
  with gr.TabItem("πŸ… Leaderboard"):
169
  leaderboard_output = gr.Dataframe(label="Leaderboard")
170
  demo.load(load_leaderboard, outputs=leaderboard_output)
171
  refresh_button = gr.Button("Refresh Leaderboard")
172
+
173
  def refresh_leaderboard():
174
  return load_leaderboard()
175
+
176
  refresh_button.click(refresh_leaderboard, outputs=leaderboard_output)
177
+
178
  with gr.TabItem("πŸš€ Submit CSV"):
179
+ gr.Markdown(
180
+ "**Submit your predictions CSV file.** Required columns:\n\n"
181
+ "`image_name, class_id, xmin, ymin, xmax, ymax, weight`"
182
+ )
183
+
184
+ submission_file = gr.File(
185
+ label="Upload Submission CSV", file_types=[".csv"]
186
+ )
187
  submission_name_textbox = gr.Textbox(label="Submission Name / Your Name")
188
  model_description_textbox = gr.Textbox(label="Model Description / Model Name")
189
  submit_button = gr.Button("Evaluate Submission")
190
  evaluation_output = gr.Markdown()
191
+
192
  submit_button.click(
193
  evaluate_and_refresh,
194
  inputs=[submission_file, submission_name_textbox, model_description_textbox],