xsponenta commited on
Commit
9cbefb9
·
1 Parent(s): 56f1ec6

Add learned + classical pipeline ensemble (LOCAL only, push tomorrow)

Browse files

After hybrid_merge, also run predict_wireframe_sklearn (the full
classical pipeline with line cloud, winner candidates, sklearn edge
classifier, track ensemble) and union its output with the
learned-pipeline output via ensemble_merge.

ensemble_merge:
- Vertex union with close-pair merging (0.4m radius via cKDTree).
- Edge union after re-mapping classical edge endpoints onto merged
vertex indices, deduplicating undirected edge pairs.
- Robust to NaN/Inf vertices from the classical side.

Wrapped in try/except so a sklearn-pipeline failure on any sample
falls back to the existing learned + hybrid_merge output. Independent
error modes between the two pipelines should complement each other
(semantic 2D detection + line cloud + sklearn classifier vs learned 3D
segment regression).

DO NOT PUSH today — daily submission slot already used (commit 56f1ec6
scored 0.4584). Push tomorrow when budget refreshes.

Files changed (1) hide show
  1. script.py +83 -2
script.py CHANGED
@@ -307,6 +307,71 @@ def hybrid_merge(pred_v, pred_e, track_v, track_e, merge_radius=0.8):
307
 
308
  return np.array(final_v), final_e
309
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
310
  # ---------------------------------------------------------------------------
311
  # Main
312
  # ---------------------------------------------------------------------------
@@ -397,11 +462,27 @@ if __name__ == "__main__":
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()}")
 
307
 
308
  return np.array(final_v), final_e
309
 
310
+
311
+ def ensemble_merge(v1, e1, v2, e2, vertex_merge_radius=0.4):
312
+ """Merge two pipeline outputs (learned + classical) into a single wireframe.
313
+
314
+ Strategy: vertex union with merging of close pairs, edge union after
315
+ re-mapping classical-pipeline edge endpoints onto merged vertex indices.
316
+
317
+ Both inputs are expected to be (vertices ndarray/list, edges list-of-tuples).
318
+ """
319
+ v1 = np.array(v1, dtype=np.float64) if isinstance(v1, list) else np.asarray(v1, dtype=np.float64)
320
+ v2 = np.array(v2, dtype=np.float64) if isinstance(v2, list) else np.asarray(v2, dtype=np.float64)
321
+
322
+ if v2.size == 0 or len(v2) == 0:
323
+ return v1, list(e1)
324
+ if v1.size == 0 or len(v1) == 0:
325
+ return v2, list(e2)
326
+
327
+ # Filter out non-finite vertices in v2
328
+ valid2 = np.isfinite(v2).all(axis=1)
329
+ if not valid2.all():
330
+ idx_map_2 = {int(old): new for new, old in enumerate(np.where(valid2)[0])}
331
+ v2 = v2[valid2]
332
+ e2 = [(idx_map_2[int(u)], idx_map_2[int(v)]) for u, v in e2
333
+ if int(u) in idx_map_2 and int(v) in idx_map_2]
334
+
335
+ if len(v2) == 0:
336
+ return v1, list(e1)
337
+
338
+ from scipy.spatial import cKDTree
339
+ tree = cKDTree(v1)
340
+ dists, indices = tree.query(v2, k=1)
341
+
342
+ v2_to_merged = {}
343
+ new_vertices = []
344
+ for i, (d, j) in enumerate(zip(dists, indices)):
345
+ if d <= vertex_merge_radius:
346
+ v2_to_merged[i] = int(j)
347
+ else:
348
+ v2_to_merged[i] = len(v1) + len(new_vertices)
349
+ new_vertices.append(v2[i])
350
+
351
+ final_v = np.vstack([v1, np.array(new_vertices, dtype=np.float64)]) if new_vertices else v1
352
+ final_e_set = set()
353
+ final_e = []
354
+ for u, v in e1:
355
+ u, v = int(u), int(v)
356
+ if u == v:
357
+ continue
358
+ e = (min(u, v), max(u, v))
359
+ if e not in final_e_set:
360
+ final_e_set.add(e)
361
+ final_e.append(e)
362
+ for u, v in e2:
363
+ u_m = v2_to_merged.get(int(u))
364
+ v_m = v2_to_merged.get(int(v))
365
+ if u_m is None or v_m is None or u_m == v_m:
366
+ continue
367
+ e = (min(u_m, v_m), max(u_m, v_m))
368
+ if e not in final_e_set:
369
+ final_e_set.add(e)
370
+ final_e.append(e)
371
+
372
+ return final_v, final_e
373
+
374
+
375
  # ---------------------------------------------------------------------------
376
  # Main
377
  # ---------------------------------------------------------------------------
 
462
  from triangulation import predict_wireframe_tracks
463
  # Use min_views=3 for highly precise, conservative geometric tracks
464
  track_v, track_e = predict_wireframe_tracks(sample, min_views=3)
465
+
466
  pred_v, pred_e = hybrid_merge(pred_v, pred_e, track_v, track_e, merge_radius=0.8)
467
  except Exception as track_e_err:
468
  print(f" Track ensemble failed for {order_id}: {track_e_err}")
469
+
470
+ # Pipeline ensemble: also run the classical sklearn pipeline
471
+ # and union with the learned-pipeline output. Independent
472
+ # error modes (semantic 2D detection + line cloud + sklearn
473
+ # edge classifier) complement the learned 3D segment regression.
474
+ try:
475
+ from sklearn_submission import predict_wireframe_sklearn
476
+ skl_v, skl_e = predict_wireframe_sklearn(sample)
477
+ if isinstance(pred_v, np.ndarray) and len(pred_v) >= 1 and \
478
+ skl_v is not None and len(skl_v) >= 1:
479
+ pred_v, pred_e = ensemble_merge(
480
+ pred_v, pred_e, skl_v, skl_e,
481
+ vertex_merge_radius=0.4,
482
+ )
483
+ except Exception as ens_err:
484
+ print(f" Ensemble merge failed for {order_id}: {ens_err}")
485
+
486
  except Exception as e:
487
  import traceback
488
  print(f" Predict failed for {order_id}:\n{traceback.format_exc()}")