Other
PyTorch
3d-reconstruction
wireframe
building
point-cloud
s23dr
cvpr-2026
File size: 2,268 Bytes
f4487da
 
 
 
 
465f2c6
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
f4487da
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
from __future__ import annotations

import numpy as np


def merge_vertices_iterative(vertices: np.ndarray, edges: np.ndarray,
                              start: float = 0.15, end: float = 0.6,
                              n_iters: int = 5):
    """Iterative merge: start with tight threshold, gradually widen.

    Avoids the worst transitive chaining effects of a single wide threshold.
    Each pass merges only the closest pairs first, establishing stable cluster
    centers before wider merges pull in more distant endpoints.

    +0.004 HSS / +0.007 F1 over single-pass merge(0.4) on 1024 val samples.
    """
    pv, pe = vertices, edges
    for t in np.linspace(start, end, n_iters):
        pv, pe = merge_vertices(pv, pe, t)
    return pv, pe


def merge_vertices(vertices: np.ndarray, edges: np.ndarray, thresh: float):
    verts = np.asarray(vertices, dtype=np.float32)
    edges = np.asarray(edges, dtype=np.int64)
    if verts.size == 0 or edges.size == 0:
        return verts, edges

    n = verts.shape[0]
    parent = np.arange(n, dtype=np.int64)

    def find(i):
        while parent[i] != i:
            parent[i] = parent[parent[i]]
            i = parent[i]
        return i

    def union(i, j):
        ri = find(i)
        rj = find(j)
        if ri != rj:
            parent[rj] = ri

    for i in range(n):
        vi = verts[i]
        for j in range(i + 1, n):
            if np.linalg.norm(vi - verts[j]) <= thresh:
                union(i, j)

    clusters = {}
    for i in range(n):
        root = find(i)
        clusters.setdefault(root, []).append(i)

    new_vertices = []
    mapping = {}
    for new_idx, idxs in enumerate(clusters.values()):
        pts = verts[idxs]
        center = pts.mean(axis=0)
        new_vertices.append(center)
        for i in idxs:
            mapping[i] = new_idx

    new_edges = []
    seen = set()
    for a, b in edges:
        na = mapping.get(int(a), int(a))
        nb = mapping.get(int(b), int(b))
        if na == nb:
            continue
        key = (na, nb) if na <= nb else (nb, na)
        if key in seen:
            continue
        seen.add(key)
        new_edges.append([na, nb])

    return np.asarray(new_vertices, dtype=np.float32), np.asarray(new_edges, dtype=np.int64)