File size: 6,344 Bytes
f6dd1c2
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
import os
import numpy as np
import trimesh
from plyfile import PlyData
import pyregister


def read_vertices_normals(file_path):
    """
    Read vertices and normals from a point cloud or mesh file.
    Supports formats such as .ply, .obj, .xyz, etc.
    """
    ext = os.path.splitext(file_path)[1].lower()

    if ext == ".ply":
        plydata = PlyData.read(file_path)
        vertex_data = plydata['vertex']
        vertices = np.vstack([vertex_data['x'], vertex_data['y'], vertex_data['z']]).astype(np.float64)

        normals = None
        if {'nx', 'ny', 'nz'}.issubset(vertex_data.data.dtype.names):
            normals = np.vstack([vertex_data['nx'], vertex_data['ny'], vertex_data['nz']]).astype(np.float64)

    else:
        mesh = trimesh.load(file_path, process=False)
        vertices = mesh.vertices.T.astype(np.float64)
        normals = getattr(mesh, "vertex_normals", None)
        if normals is not None and len(normals) > 0:
            normals = normals.T.astype(np.float64)
        else:
            normals = np.empty((0, 0))

    return vertices, normals


def run_rigid_file(file_target, file_source, output_path):
    """
    Perform rigid registration (FRICP method) by directly reading files.

    Parameters
    ----------
    file_target : str
        Path to the target point cloud or mesh file.
    file_source : str
        Path to the source point cloud or mesh file.
    output_path : str
        Output file path for the registered result.
    """
    print(f"\n[RIGID-FILE] Registering {file_source} β†’ {file_target}")
    reg = pyregister.RigidFricpRegistration()
    reg.Paras_init(useinit=False, maxiter=100, stop=1e-5)
    reg.Reg(file_target, file_source, output_path)
    print(f"[RIGID-FILE] Completed β†’ {output_path}")
    print("Deformed points shape:", reg.deformed_points_3X_.shape)


def run_rigid_numpy(target_pts, source_pts, target_n, source_n, output_path):
    """
    Perform rigid registration (FRICP method) using NumPy matrices.

    Parameters
    ----------
    target_pts : np.ndarray, shape (3, N)
        Target point cloud coordinates.
    source_pts : np.ndarray, shape (3, N)
        Source point cloud coordinates.
    target_n : np.ndarray, shape (3, N) or (0, 0)
        Target normals.
    source_n : np.ndarray, shape (3, N) or (0, 0)
        Source normals.
    output_path : str
        Output file path for the registered result.
    """
    print(f"\n[RIGID-NUMPY] Registering from NumPy matrices")
    reg = pyregister.RigidFricpRegistration()
    reg.Paras_init()
    reg.Read_data(target_pts, source_pts, target_n, source_n)
    reg.Register()
    reg.Output_data(output_path, "FRICP")
    print(f"[RIGID-NUMPY] Completed β†’ {output_path}")
    print("Deformed points shape:", reg.deformed_points_3X_.shape)


def run_nonrigid_file(file_target, file_source, output_path):
    """
    Perform non-rigid registration (SPARE method) by directly reading files.

    Parameters
    ----------
    file_target : str
        Path to the target point cloud or mesh file.
    file_source : str
        Path to the source point cloud or mesh file.
    output_path : str
        Output file path for the registered result.
    """
    print(f"\n[NONRIGID-FILE] Registering {file_source} β†’ {file_target}")
    reg = pyregister.NonrigidSpareRegistration()
    reg.Paras_init(iters = 30 ,stopcoarse=1e-3,stopfine=1e-4, uselandmark = False);
    reg.Reg(file_target, file_source, output_path)
    print(f"[NONRIGID-FILE] Completed β†’ {output_path}")
    print("Deformed points shape:", reg.deformed_points_3X_.shape)



def run_nonrigid_numpy(target_pts, source_pts, target_n, source_n, output_path):
    """
    Perform non-rigid registration (SPARE method) using NumPy matrices.

    Parameters
    ----------
    target_pts : np.ndarray, shape (3, N)
        Target point cloud coordinates.
    source_pts : np.ndarray, shape (3, N)
        Source point cloud coordinates.
    target_n : np.ndarray, shape (3, N) or (0, 0)
        Target normals.
    source_n : np.ndarray, shape (3, N) or (0, 0)
        Source normals.
    output_path : str
        Output file path for the registered result.
    """
    print(f"\n[NONRIGID-NUMPY] Registering from NumPy matrices")
    reg = pyregister.NonrigidSpareRegistration()
    reg.Paras_init()
    reg.Read_data(target_pts, source_pts, target_n, source_n)
    reg.Register()
    reg.Output_data(output_path, "SPARE")
    print(f"[NONRIGID-NUMPY] Completed β†’ {output_path}")
    print("Deformed points shape:", reg.deformed_points_3X_.shape)



def main():
    folder = "data"
    output_folder = os.path.join(folder, "results_register")
    os.makedirs(output_folder, exist_ok=True)
    target_ply = os.path.join(folder, "target.ply")

    source_ply = os.path.join(folder, "source.ply")

    target_obj = os.path.join(folder, "target.obj")

    source_obj = os.path.join(folder, "source.obj")

    # Rigid registration (file mode)
    if os.path.exists(target_ply) and os.path.exists(source_ply):
        run_rigid_file(target_ply, source_ply, os.path.join(output_folder, "rigid_file_result"))

        # Load into NumPy and run in-memory registration
        target_pts, target_n = read_vertices_normals(target_ply)
        source_pts, source_n = read_vertices_normals(source_ply)
        target_n = target_n if target_n is not None else np.empty((0, 0))
        source_n = source_n if source_n is not None else np.empty((0, 0))
        run_rigid_numpy(target_pts, source_pts, target_n, source_n,
                        os.path.join(output_folder, "rigid_numpy_result"))

    # Non-rigid registration (file mode)
    if os.path.exists( target_obj ) and os.path.exists(source_obj):
        run_nonrigid_file( target_obj , source_obj, os.path.join(output_folder, "nonrigid_file_result"))

        # Load into NumPy and run in-memory registration
        target_pts, target_n = read_vertices_normals( target_obj )
        source_pts, source_n = read_vertices_normals(source_obj)
        target_n = target_n if target_n is not None else np.empty((0, 0))
        source_n = source_n if source_n is not None else np.empty((0, 0))
        run_nonrigid_numpy(target_pts, source_pts, target_n, source_n,
                           os.path.join(output_folder, "nonrigid_numpy_result"))


if __name__ == "__main__":
    main()