xsponenta commited on
Commit
61a6827
·
1 Parent(s): 6cf3fbd

Revert: roll back COLMAP refine + junction + snap changes

Browse files

The previous commit's changes regressed the leaderboard score:
- hss_mean: 0.4583 -> 0.4443 (-0.014)
- corner_f1: 0.5104 -> 0.5003 (-0.010)
- edge_iou: 0.4268 -> 0.4101 (-0.017)

Most likely culprits without local validation:
- COLMAP multi-view plane refinement: snapped some vertices onto wall
or ground planes instead of roof planes (corner_f1 hit).
- Junction constraints: the leaf_min_len=0.4m and collinear_cos=0.97
thresholds removed valid short edges and corner vertices (edge_iou hit).
- Loosened hybrid_merge admitted incorrect track edges between
existing predicted vertices.

Restore script.py and s23dr_2026_example/postprocess_v2.py to the state
from commit 9deb9e1 (the previous best, hss_mean=0.4583). Tomorrow we
can attempt smaller, targeted experiments one at a time.

Files changed (2) hide show
  1. s23dr_2026_example/postprocess_v2.py +8 -33
  2. script.py +11 -64
s23dr_2026_example/postprocess_v2.py CHANGED
@@ -6,7 +6,7 @@ def snap_to_point_cloud(vertices, xyz, class_id, snap_radius=0.5,
6
  target_classes=None):
7
  """Snap vertices to nearby point cloud clusters of specific semantic classes."""
8
  if target_classes is None:
9
- target_classes = [1, 2, 3] # apex, eave_end_point, flashing_end_point
10
 
11
  snapped = vertices.copy()
12
  mask = np.isin(class_id, target_classes)
@@ -26,39 +26,14 @@ def snap_to_point_cloud(vertices, xyz, class_id, snap_radius=0.5,
26
 
27
 
28
  def snap_horizontal(vertices, edges, max_slope=0.05):
29
- """Snap near-horizontal edges to be exactly horizontal.
30
-
31
- Only snaps a vertex if ALL of its incident edges are near-horizontal —
32
- otherwise we would corrupt sloped edges that share the vertex.
33
- """
34
  verts = vertices.copy()
35
- n = len(verts)
36
- if n == 0 or len(edges) == 0:
37
- return verts
38
-
39
- edge_is_h = []
40
- incident = [[] for _ in range(n)]
41
- for ei, (a, b) in enumerate(edges):
42
  a, b = int(a), int(b)
43
  dy = abs(verts[a, 1] - verts[b, 1])
44
- dxz = np.sqrt((verts[a, 0] - verts[b, 0]) ** 2 + (verts[a, 2] - verts[b, 2]) ** 2)
45
- is_h = dxz > 0.1 and dy / dxz < max_slope
46
- edge_is_h.append(is_h)
47
- incident[a].append(ei)
48
- incident[b].append(ei)
49
-
50
- purely_h = [
51
- len(incident[v]) > 0 and all(edge_is_h[ei] for ei in incident[v])
52
- for v in range(n)
53
- ]
54
-
55
- for ei, (a, b) in enumerate(edges):
56
- if not edge_is_h[ei]:
57
- continue
58
- a, b = int(a), int(b)
59
- if not (purely_h[a] and purely_h[b]):
60
- continue
61
- avg_y = 0.5 * (verts[a, 1] + verts[b, 1])
62
- verts[a, 1] = avg_y
63
- verts[b, 1] = avg_y
64
  return verts
 
6
  target_classes=None):
7
  """Snap vertices to nearby point cloud clusters of specific semantic classes."""
8
  if target_classes is None:
9
+ target_classes = [1, 2] # apex, eave_end_point
10
 
11
  snapped = vertices.copy()
12
  mask = np.isin(class_id, target_classes)
 
26
 
27
 
28
  def snap_horizontal(vertices, edges, max_slope=0.05):
29
+ """Snap near-horizontal edges to be exactly horizontal."""
 
 
 
 
30
  verts = vertices.copy()
31
+ for a, b in edges:
 
 
 
 
 
 
32
  a, b = int(a), int(b)
33
  dy = abs(verts[a, 1] - verts[b, 1])
34
+ dxz = np.sqrt((verts[a, 0] - verts[b, 0])**2 + (verts[a, 2] - verts[b, 2])**2)
35
+ if dxz > 0.1 and dy / dxz < max_slope:
36
+ avg_y = 0.5 * (verts[a, 1] + verts[b, 1])
37
+ verts[a, 1] = avg_y
38
+ verts[b, 1] = avg_y
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
39
  return verts
script.py CHANGED
@@ -293,38 +293,18 @@ def hybrid_merge(pred_v, pred_e, track_v, track_e, merge_radius=0.8):
293
  for u, v in final_e:
294
  existing_edges.add((min(u, v), max(u, v)))
295
 
296
- # Tight-confidence radius for accepting a track edge between two
297
- # already-existing predicted vertices (topology correction).
298
- tight_radius = 0.3
299
-
300
  for u_t, v_t in track_e:
301
  u_f = track_to_final.get(u_t)
302
  v_f = track_to_final.get(v_t)
303
- if u_f is None or v_f is None or u_f == v_f:
304
- continue
305
- e = (min(u_f, v_f), max(u_f, v_f))
306
- if e in existing_edges:
307
- continue
308
-
309
- u_is_new = u_f >= len(pred_v)
310
- v_is_new = v_f >= len(pred_v)
311
-
312
- if u_is_new or v_is_new:
313
- # New vertex: trust the track edge.
314
- final_e.append(e)
315
- existing_edges.add(e)
316
- continue
317
-
318
- # Both endpoints are existing predicted vertices — only accept the
319
- # track edge as a topology correction when both are very confidently
320
- # matched (tight distance). This recovers missing edges without
321
- # letting the tracker rewire the learned topology.
322
- d_u = dists[u_t] if u_t < len(dists) else np.inf
323
- d_v = dists[v_t] if v_t < len(dists) else np.inf
324
- if d_u <= tight_radius and d_v <= tight_radius:
325
- final_e.append(e)
326
- existing_edges.add(e)
327
-
328
  return np.array(final_v), final_e
329
 
330
  # ---------------------------------------------------------------------------
@@ -417,44 +397,11 @@ if __name__ == "__main__":
417
  from triangulation import predict_wireframe_tracks
418
  # Use min_views=3 for highly precise, conservative geometric tracks
419
  track_v, track_e = predict_wireframe_tracks(sample, min_views=3)
420
-
421
  pred_v, pred_e = hybrid_merge(pred_v, pred_e, track_v, track_e, merge_radius=0.8)
422
  except Exception as track_e_err:
423
  print(f" Track ensemble failed for {order_id}: {track_e_err}")
424
-
425
- # COLMAP multi-view plane refinement: snaps each vertex to the
426
- # roof plane visible at its 2D projection. Targets corner_f1.
427
- try:
428
- if isinstance(pred_v, np.ndarray) and len(pred_v) >= 1:
429
- from colmap_refine import refine_vertices_multiview_plane
430
- refined, snapped_mask = refine_vertices_multiview_plane(
431
- pred_v, sample,
432
- knn_2d_px=30.0, knn_k=12, min_neighbours=6,
433
- max_displacement=0.5, min_quality=0.5, min_views=2,
434
- )
435
- if snapped_mask.any():
436
- pred_v = refined
437
- except Exception as refine_err:
438
- print(f" COLMAP refine failed for {order_id}: {refine_err}")
439
-
440
- # Junction constraints: drop collinear/duplicate/short-leaf edges
441
- try:
442
- if isinstance(pred_v, np.ndarray) and len(pred_v) >= 2 and len(pred_e) >= 1:
443
- from junction import apply_junction_constraints
444
- jv, je = apply_junction_constraints(
445
- pred_v, pred_e,
446
- collinear_cos=0.97,
447
- duplicate_cos=0.985,
448
- leaf_min_len=0.4,
449
- max_passes=3,
450
- )
451
- # Only accept if at least one edge survives — never let
452
- # the post-processing reduce us to an empty graph.
453
- if len(je) >= 1:
454
- pred_v, pred_e = jv, je
455
- except Exception as junc_err:
456
- print(f" Junction constraints failed for {order_id}: {junc_err}")
457
-
458
  except Exception as e:
459
  import traceback
460
  print(f" Predict failed for {order_id}:\n{traceback.format_exc()}")
 
293
  for u, v in final_e:
294
  existing_edges.add((min(u, v), max(u, v)))
295
 
 
 
 
 
296
  for u_t, v_t in track_e:
297
  u_f = track_to_final.get(u_t)
298
  v_f = track_to_final.get(v_t)
299
+ if u_f is not None and v_f is not None and u_f != v_f:
300
+ e = (min(u_f, v_f), max(u_f, v_f))
301
+ if e not in existing_edges:
302
+ # ONLY append the tracked edge if it connects to a NEWLY DISCOVERED vertex.
303
+ # This prevents the geometric tracker from aggressively re-wiring the learned model's existing topology!
304
+ if u_f >= len(pred_v) or v_f >= len(pred_v):
305
+ final_e.append(e)
306
+ existing_edges.add(e)
307
+
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
308
  return np.array(final_v), final_e
309
 
310
  # ---------------------------------------------------------------------------
 
397
  from triangulation import predict_wireframe_tracks
398
  # Use min_views=3 for highly precise, conservative geometric tracks
399
  track_v, track_e = predict_wireframe_tracks(sample, min_views=3)
400
+
401
  pred_v, pred_e = hybrid_merge(pred_v, pred_e, track_v, track_e, merge_radius=0.8)
402
  except Exception as track_e_err:
403
  print(f" Track ensemble failed for {order_id}: {track_e_err}")
404
+
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
405
  except Exception as e:
406
  import traceback
407
  print(f" Predict failed for {order_id}:\n{traceback.format_exc()}")