Rhapso 0.1.99__py3-none-any.whl → 0.1.993__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- Rhapso/matching/ransac_matching.py +32 -36
- Rhapso/pipelines/ray/aws/alignment_pipeline.py +17 -14
- Rhapso/pipelines/ray/interest_point_matching.py +9 -9
- Rhapso/pipelines/ray/local/alignment_pipeline.py +20 -17
- Rhapso/pipelines/ray/solver.py +7 -3
- Rhapso/solver/global_optimization.py +5 -5
- Rhapso/split_dataset/save_xml.py +490 -93
- {rhapso-0.1.99.dist-info → rhapso-0.1.993.dist-info}/METADATA +38 -26
- {rhapso-0.1.99.dist-info → rhapso-0.1.993.dist-info}/RECORD +12 -12
- {rhapso-0.1.99.dist-info → rhapso-0.1.993.dist-info}/WHEEL +0 -0
- {rhapso-0.1.99.dist-info → rhapso-0.1.993.dist-info}/licenses/LICENSE +0 -0
- {rhapso-0.1.99.dist-info → rhapso-0.1.993.dist-info}/top_level.txt +0 -0
|
@@ -27,7 +27,7 @@ class CustomBioImage(BioImage):
|
|
|
27
27
|
|
|
28
28
|
class RansacMatching:
|
|
29
29
|
def __init__(self, data_global, num_neighbors, redundancy, significance, num_required_neighbors, match_type,
|
|
30
|
-
|
|
30
|
+
inlier_threshold, min_inlier_ratio, num_iterations, model_min_matches, regularization_weight,
|
|
31
31
|
search_radius, view_registrations, input_type, image_file_prefix):
|
|
32
32
|
self.data_global = data_global
|
|
33
33
|
self.num_neighbors = num_neighbors
|
|
@@ -35,7 +35,7 @@ class RansacMatching:
|
|
|
35
35
|
self.significance = significance
|
|
36
36
|
self.num_required_neighbors = num_required_neighbors
|
|
37
37
|
self.match_type = match_type
|
|
38
|
-
self.
|
|
38
|
+
self.inlier_threshold = inlier_threshold
|
|
39
39
|
self.min_inlier_ratio = min_inlier_ratio
|
|
40
40
|
self.num_iterations = num_iterations
|
|
41
41
|
self.model_min_matches = model_min_matches
|
|
@@ -66,7 +66,7 @@ class RansacMatching:
|
|
|
66
66
|
errors = []
|
|
67
67
|
for match in temp:
|
|
68
68
|
p1 = np.array(match[1])
|
|
69
|
-
p2 = np.array(match[
|
|
69
|
+
p2 = np.array(match[5])
|
|
70
70
|
p1_h = np.append(p1, 1.0)
|
|
71
71
|
p1_trans = model_copy @ p1_h
|
|
72
72
|
error = np.linalg.norm(p1_trans[:3] - p2)
|
|
@@ -137,60 +137,55 @@ class RansacMatching:
|
|
|
137
137
|
rigid_matrix[:3, 3] = t
|
|
138
138
|
|
|
139
139
|
return rigid_matrix
|
|
140
|
-
|
|
140
|
+
|
|
141
141
|
def fit_affine_model(self, matches):
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
142
|
+
"""
|
|
143
|
+
Fit a 3x4 affine transform such that:
|
|
144
|
+
Q ≈ M @ P + t
|
|
145
|
+
where P, Q are 3D column vectors (but stored here as row vectors).
|
|
146
|
+
"""
|
|
147
|
+
matches = np.asarray(matches) # shape (N, 2, 3)
|
|
148
|
+
P = matches[:, 0] # source points, shape (N, 3)
|
|
149
|
+
Q = matches[:, 1] # target points, shape (N, 3)
|
|
146
150
|
|
|
147
|
-
|
|
151
|
+
# Uniform weights for now (kept in case you add non-uniform later)
|
|
152
|
+
weights = np.ones(P.shape[0], dtype=float)
|
|
148
153
|
|
|
154
|
+
# Weighted centroids
|
|
149
155
|
pc = np.average(P, axis=0, weights=weights)
|
|
150
156
|
qc = np.average(Q, axis=0, weights=weights)
|
|
151
157
|
|
|
158
|
+
# Centered coordinates
|
|
152
159
|
P_centered = P - pc
|
|
153
160
|
Q_centered = Q - qc
|
|
154
161
|
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
w = weights[i]
|
|
160
|
-
p = P_centered[i]
|
|
161
|
-
q = Q_centered[i]
|
|
162
|
-
|
|
163
|
-
A += w * np.outer(p, p)
|
|
164
|
-
B += w * np.outer(p, q)
|
|
162
|
+
# Weighted least squares: scale rows by sqrt(weight)
|
|
163
|
+
sqrt_w = np.sqrt(weights)[:, None] # (N, 1)
|
|
164
|
+
P_w = P_centered * sqrt_w # (N, 3)
|
|
165
|
+
Q_w = Q_centered * sqrt_w # (N, 3)
|
|
165
166
|
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
167
|
+
# Solve P_w @ M^T ≈ Q_w → M_T is 3x3, then transpose
|
|
168
|
+
M_T, *_ = np.linalg.lstsq(P_w, Q_w, rcond=None)
|
|
169
|
+
M = M_T.T
|
|
169
170
|
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
except np.linalg.LinAlgError:
|
|
173
|
-
# If A is not invertible, use the pseudo-inverse
|
|
174
|
-
A_inv = np.linalg.pinv(A)
|
|
171
|
+
# Translation so that M @ pc ≈ qc
|
|
172
|
+
t = qc - M @ pc
|
|
175
173
|
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
t = qc - M @ pc # translation
|
|
179
|
-
|
|
180
|
-
affine_matrix = np.eye(4)
|
|
174
|
+
# Pack into 4x4 affine matrix
|
|
175
|
+
affine_matrix = np.eye(4, dtype=float)
|
|
181
176
|
affine_matrix[:3, :3] = M
|
|
182
177
|
affine_matrix[:3, 3] = t
|
|
183
178
|
|
|
184
179
|
return affine_matrix
|
|
185
180
|
|
|
186
|
-
def test(self, candidates, model,
|
|
181
|
+
def test(self, candidates, model, inlier_threshold, min_inlier_ratio, min_num_inliers):
|
|
187
182
|
inliers = []
|
|
188
183
|
for idxA, pointA, view_a, label_a, idxB, pointB, view_b, label_b in candidates:
|
|
189
184
|
p1_hom = np.append(pointA, 1.0)
|
|
190
185
|
transformed = model @ p1_hom
|
|
191
186
|
distance = np.linalg.norm(transformed[:3] - pointB)
|
|
192
187
|
|
|
193
|
-
if distance <
|
|
188
|
+
if distance < inlier_threshold:
|
|
194
189
|
inliers.append((idxA, pointA, view_a, label_a, idxB, pointB, view_b, label_b))
|
|
195
190
|
|
|
196
191
|
ir = len(inliers) / len(candidates)
|
|
@@ -251,15 +246,16 @@ class RansacMatching:
|
|
|
251
246
|
regularized_model = self.model_regularization(point_pairs)
|
|
252
247
|
except Exception as e:
|
|
253
248
|
print(e)
|
|
249
|
+
continue
|
|
254
250
|
|
|
255
251
|
num_inliers = 0
|
|
256
|
-
is_good, tmp_inliers = self.test(candidates, regularized_model, self.
|
|
252
|
+
is_good, tmp_inliers = self.test(candidates, regularized_model, self.inlier_threshold, self.min_inlier_ratio, self.model_min_matches)
|
|
257
253
|
|
|
258
254
|
while is_good and num_inliers < len(tmp_inliers):
|
|
259
255
|
num_inliers = len(tmp_inliers)
|
|
260
256
|
point_pairs = [(i[1], i[5]) for i in tmp_inliers]
|
|
261
257
|
regularized_model = self.model_regularization(point_pairs)
|
|
262
|
-
is_good, tmp_inliers = self.test(candidates, regularized_model, self.
|
|
258
|
+
is_good, tmp_inliers = self.test(candidates, regularized_model, self.inlier_threshold, self.min_inlier_ratio, self.model_min_matches)
|
|
263
259
|
|
|
264
260
|
if len(tmp_inliers) > max_inliers:
|
|
265
261
|
best_inliers = tmp_inliers
|
|
@@ -5,7 +5,7 @@ import json
|
|
|
5
5
|
import base64, json
|
|
6
6
|
from pathlib import Path
|
|
7
7
|
|
|
8
|
-
with open("Rhapso/pipelines/ray/param/
|
|
8
|
+
with open("Rhapso/pipelines/ray/param/exaSPIM_802450.yml", "r") as file:
|
|
9
9
|
config = yaml.safe_load(file)
|
|
10
10
|
|
|
11
11
|
serialized_config = base64.b64encode(json.dumps(config).encode()).decode()
|
|
@@ -51,10 +51,10 @@ matching_cmd_rigid = (
|
|
|
51
51
|
" search_radius=cfg[\\\"search_radius_rigid\\\"],\n"
|
|
52
52
|
" num_required_neighbors=cfg[\\\"num_required_neighbors_rigid\\\"],\n"
|
|
53
53
|
" model_min_matches=cfg[\\\"model_min_matches_rigid\\\"],\n"
|
|
54
|
-
"
|
|
55
|
-
"
|
|
54
|
+
" inlier_threshold=cfg[\\\"inlier_threshold_rigid\\\"],\n"
|
|
55
|
+
" min_inlier_ratio=cfg[\\\"min_inlier_ratio_rigid\\\"],\n"
|
|
56
56
|
" num_iterations=cfg[\\\"num_iterations_rigid\\\"],\n"
|
|
57
|
-
" regularization_weight=cfg[\\\"
|
|
57
|
+
" regularization_weight=cfg[\\\"regularization_weight_matching_rigid\\\"],\n"
|
|
58
58
|
" image_file_prefix=cfg[\\\"image_file_prefix\\\"]\n"
|
|
59
59
|
")\n"
|
|
60
60
|
"ipm.run()\n"
|
|
@@ -80,10 +80,10 @@ matching_cmd_affine = (
|
|
|
80
80
|
" search_radius=cfg[\\\"search_radius_affine\\\"],\n"
|
|
81
81
|
" num_required_neighbors=cfg[\\\"num_required_neighbors_affine\\\"],\n"
|
|
82
82
|
" model_min_matches=cfg[\\\"model_min_matches_affine\\\"],\n"
|
|
83
|
-
"
|
|
84
|
-
"
|
|
83
|
+
" inlier_threshold=cfg[\\\"inlier_threshold_affine\\\"],\n"
|
|
84
|
+
" min_inlier_ratio=cfg[\\\"min_inlier_ratio_affine\\\"],\n"
|
|
85
85
|
" num_iterations=cfg[\\\"num_iterations_affine\\\"],\n"
|
|
86
|
-
" regularization_weight=cfg[\\\"
|
|
86
|
+
" regularization_weight=cfg[\\\"regularization_weight_matching_affine\\\"],\n"
|
|
87
87
|
" image_file_prefix=cfg[\\\"image_file_prefix\\\"]\n"
|
|
88
88
|
")\n"
|
|
89
89
|
"ipm.run()\n"
|
|
@@ -109,10 +109,10 @@ matching_cmd_split_affine = (
|
|
|
109
109
|
" search_radius=cfg[\\\"search_radius_split_affine\\\"],\n"
|
|
110
110
|
" num_required_neighbors=cfg[\\\"num_required_neighbors_split_affine\\\"],\n"
|
|
111
111
|
" model_min_matches=cfg[\\\"model_min_matches_split_affine\\\"],\n"
|
|
112
|
-
"
|
|
113
|
-
"
|
|
112
|
+
" inlier_threshold=cfg[\\\"inlier_threshold_split_affine\\\"],\n"
|
|
113
|
+
" min_inlier_ratio=cfg[\\\"min_inlier_ratio_split_affine\\\"],\n"
|
|
114
114
|
" num_iterations=cfg[\\\"num_iterations_split_affine\\\"],\n"
|
|
115
|
-
" regularization_weight=cfg[\\\"
|
|
115
|
+
" regularization_weight=cfg[\\\"regularization_weight_matching_split_affine\\\"],\n"
|
|
116
116
|
" image_file_prefix=cfg[\\\"image_file_prefix\\\"]\n"
|
|
117
117
|
")\n"
|
|
118
118
|
"ipm.run()\n"
|
|
@@ -151,6 +151,7 @@ solver_rigid = Solver(
|
|
|
151
151
|
absolute_threshold=config['absolute_threshold'],
|
|
152
152
|
min_matches=config['min_matches'],
|
|
153
153
|
damp=config['damp'],
|
|
154
|
+
regularization_weight=config['regularization_weight_solver_rigid'],
|
|
154
155
|
max_iterations=config['max_iterations'],
|
|
155
156
|
max_allowed_error=config['max_allowed_error'],
|
|
156
157
|
max_plateauwidth=config['max_plateauwidth'],
|
|
@@ -168,6 +169,7 @@ solver_affine = Solver(
|
|
|
168
169
|
absolute_threshold=config['absolute_threshold'],
|
|
169
170
|
min_matches=config['min_matches'],
|
|
170
171
|
damp=config['damp'],
|
|
172
|
+
regularization_weight=config['regularization_weight_solver_affine'],
|
|
171
173
|
max_iterations=config['max_iterations'],
|
|
172
174
|
max_allowed_error=config['max_allowed_error'],
|
|
173
175
|
max_plateauwidth=config['max_plateauwidth'],
|
|
@@ -185,6 +187,7 @@ solver_split_affine = Solver(
|
|
|
185
187
|
absolute_threshold=config['absolute_threshold'],
|
|
186
188
|
min_matches=config['min_matches'],
|
|
187
189
|
damp=config['damp'],
|
|
190
|
+
regularization_weight=config['regularization_weight_solver_split_affine'],
|
|
188
191
|
max_iterations=config['max_iterations'],
|
|
189
192
|
max_allowed_error=config['max_allowed_error'],
|
|
190
193
|
max_plateauwidth=config['max_plateauwidth'],
|
|
@@ -210,10 +213,10 @@ try:
|
|
|
210
213
|
solver_rigid.run()
|
|
211
214
|
exec_on_cluster("Matching (affine)", unified_yml, matching_cmd_affine, prefix)
|
|
212
215
|
solver_affine.run()
|
|
213
|
-
exec_on_cluster("Split Dataset", unified_yml, split_cmd, prefix)
|
|
214
|
-
exec_on_cluster("Matching (split_affine)", unified_yml, matching_cmd_split_affine, prefix)
|
|
215
|
-
solver_split_affine.run()
|
|
216
|
-
print("\n✅ Pipeline complete.")
|
|
216
|
+
# exec_on_cluster("Split Dataset", unified_yml, split_cmd, prefix)
|
|
217
|
+
# exec_on_cluster("Matching (split_affine)", unified_yml, matching_cmd_split_affine, prefix)
|
|
218
|
+
# solver_split_affine.run()
|
|
219
|
+
# print("\n✅ Pipeline complete.")
|
|
217
220
|
|
|
218
221
|
except subprocess.CalledProcessError as e:
|
|
219
222
|
print(f"❌ Pipeline error: {e}")
|
|
@@ -6,7 +6,7 @@ import ray
|
|
|
6
6
|
|
|
7
7
|
class InterestPointMatching:
|
|
8
8
|
def __init__(self, xml_input_path, n5_output_path, input_type, match_type, num_neighbors, redundancy, significance,
|
|
9
|
-
search_radius, num_required_neighbors, model_min_matches,
|
|
9
|
+
search_radius, num_required_neighbors, model_min_matches, inlier_threshold, min_inlier_ratio, num_iterations,
|
|
10
10
|
regularization_weight, image_file_prefix):
|
|
11
11
|
self.xml_input_path = xml_input_path
|
|
12
12
|
self.n5_output_path = n5_output_path
|
|
@@ -18,8 +18,8 @@ class InterestPointMatching:
|
|
|
18
18
|
self.search_radius = search_radius
|
|
19
19
|
self.num_required_neighbors = num_required_neighbors
|
|
20
20
|
self.model_min_matches = model_min_matches
|
|
21
|
-
self.
|
|
22
|
-
self.
|
|
21
|
+
self.inlier_threshold = inlier_threshold
|
|
22
|
+
self.min_inlier_ratio = min_inlier_ratio
|
|
23
23
|
self.num_iterations = num_iterations
|
|
24
24
|
self.regularization_weight = regularization_weight
|
|
25
25
|
self.image_file_prefix = image_file_prefix
|
|
@@ -38,11 +38,11 @@ class InterestPointMatching:
|
|
|
38
38
|
# Distribute interest point matching with Ray
|
|
39
39
|
@ray.remote
|
|
40
40
|
def match_pair(pointsA, pointsB, viewA_str, viewB_str, label, num_neighbors, redundancy, significance, num_required_neighbors,
|
|
41
|
-
match_type,
|
|
41
|
+
match_type, inlier_threshold, min_inlier_ratio, num_iterations, model_min_matches, regularization_weight, search_radius,
|
|
42
42
|
view_registrations, input_type, image_file_prefix):
|
|
43
43
|
|
|
44
|
-
matcher = RansacMatching(data_global, num_neighbors, redundancy, significance, num_required_neighbors, match_type,
|
|
45
|
-
|
|
44
|
+
matcher = RansacMatching(data_global, num_neighbors, redundancy, significance, num_required_neighbors, match_type, inlier_threshold,
|
|
45
|
+
min_inlier_ratio, num_iterations, model_min_matches, regularization_weight, search_radius, view_registrations,
|
|
46
46
|
input_type, image_file_prefix)
|
|
47
47
|
|
|
48
48
|
pointsA, pointsB = matcher.filter_for_overlapping_points(pointsA, pointsB, viewA_str, viewB_str)
|
|
@@ -65,7 +65,7 @@ class InterestPointMatching:
|
|
|
65
65
|
# --- Distribute ---
|
|
66
66
|
futures = [
|
|
67
67
|
match_pair.remote(pointsA, pointsB, viewA_str, viewB_str, label, self.num_neighbors, self.redundancy, self.significance, self.num_required_neighbors,
|
|
68
|
-
self.match_type, self.
|
|
68
|
+
self.match_type, self.inlier_threshold, self.min_inlier_ratio, self.num_iterations, self.model_min_matches, self.regularization_weight,
|
|
69
69
|
self.search_radius, view_registrations, self.input_type, self.image_file_prefix)
|
|
70
70
|
for pointsA, pointsB, viewA_str, viewB_str, label in process_pairs
|
|
71
71
|
]
|
|
@@ -88,8 +88,8 @@ class InterestPointMatching:
|
|
|
88
88
|
# DEBUG MATCHING
|
|
89
89
|
# all_results = []
|
|
90
90
|
# for pointsA, pointsB, viewA_str, viewB_str, label in process_pairs:
|
|
91
|
-
# matcher = RansacMatching(data_global, self.num_neighbors, self.redundancy, self.significance, self.num_required_neighbors, self.match_type, self.
|
|
92
|
-
# self.
|
|
91
|
+
# matcher = RansacMatching(data_global, self.num_neighbors, self.redundancy, self.significance, self.num_required_neighbors, self.match_type, self.inlier_threshold,
|
|
92
|
+
# self.min_inlier_ratio, self.num_iterations, self.model_min_matches, self.regularization_weight, self.search_radius, view_registrations,
|
|
93
93
|
# self.input_type, self.image_file_prefix)
|
|
94
94
|
|
|
95
95
|
# pointsA, pointsB = matcher.filter_for_overlapping_points(pointsA, pointsB, viewA_str, viewB_str)
|
|
@@ -9,7 +9,7 @@ import ray
|
|
|
9
9
|
ray.init()
|
|
10
10
|
|
|
11
11
|
# Point to param file
|
|
12
|
-
with open("Rhapso/pipelines/ray/param/
|
|
12
|
+
with open("Rhapso/pipelines/ray/param/exaSPIM_802450.yml", "r") as file:
|
|
13
13
|
config = yaml.safe_load(file)
|
|
14
14
|
|
|
15
15
|
# -- INITIALIZE EACH COMPONENT --
|
|
@@ -46,10 +46,10 @@ interest_point_matching_rigid = InterestPointMatching(
|
|
|
46
46
|
search_radius=config['search_radius_rigid'],
|
|
47
47
|
num_required_neighbors=config['num_required_neighbors_rigid'],
|
|
48
48
|
model_min_matches=config['model_min_matches_rigid'],
|
|
49
|
-
|
|
50
|
-
|
|
49
|
+
inlier_threshold=config['inlier_threshold_rigid'],
|
|
50
|
+
min_inlier_ratio=config['min_inlier_ratio_rigid'],
|
|
51
51
|
num_iterations=config['num_iterations_rigid'],
|
|
52
|
-
regularization_weight=config['
|
|
52
|
+
regularization_weight=config['regularization_weight_matching_rigid'],
|
|
53
53
|
image_file_prefix=config['image_file_prefix'],
|
|
54
54
|
)
|
|
55
55
|
|
|
@@ -65,10 +65,10 @@ interest_point_matching_affine = InterestPointMatching(
|
|
|
65
65
|
search_radius=config['search_radius_affine'],
|
|
66
66
|
num_required_neighbors=config['num_required_neighbors_affine'],
|
|
67
67
|
model_min_matches=config['model_min_matches_affine'],
|
|
68
|
-
|
|
69
|
-
|
|
68
|
+
inlier_threshold=config['inlier_threshold_affine'],
|
|
69
|
+
min_inlier_ratio=config['min_inlier_ratio_affine'],
|
|
70
70
|
num_iterations=config['num_iterations_affine'],
|
|
71
|
-
regularization_weight=config['
|
|
71
|
+
regularization_weight=config['regularization_weight_matching_affine'],
|
|
72
72
|
image_file_prefix=config['image_file_prefix'],
|
|
73
73
|
)
|
|
74
74
|
|
|
@@ -84,10 +84,10 @@ interest_point_matching_split_affine = InterestPointMatching(
|
|
|
84
84
|
search_radius=config['search_radius_split_affine'],
|
|
85
85
|
num_required_neighbors=config['num_required_neighbors_split_affine'],
|
|
86
86
|
model_min_matches=config['model_min_matches_split_affine'],
|
|
87
|
-
|
|
88
|
-
|
|
87
|
+
inlier_threshold=config['inlier_threshold_split_affine'],
|
|
88
|
+
min_inlier_ratio=config['min_inlier_ratio_split_affine'],
|
|
89
89
|
num_iterations=config['num_iterations_split_affine'],
|
|
90
|
-
regularization_weight=config['
|
|
90
|
+
regularization_weight=config['regularization_weight_matching_split_affine'],
|
|
91
91
|
image_file_prefix=config['image_file_prefix'],
|
|
92
92
|
)
|
|
93
93
|
|
|
@@ -101,6 +101,7 @@ solver_rigid = Solver(
|
|
|
101
101
|
absolute_threshold=config['absolute_threshold'],
|
|
102
102
|
min_matches=config['min_matches'],
|
|
103
103
|
damp=config['damp'],
|
|
104
|
+
regularization_weight=config['regularization_weight_solver_rigid'],
|
|
104
105
|
max_iterations=config['max_iterations'],
|
|
105
106
|
max_allowed_error=config['max_allowed_error'],
|
|
106
107
|
max_plateauwidth=config['max_plateauwidth'],
|
|
@@ -118,6 +119,7 @@ solver_affine = Solver(
|
|
|
118
119
|
absolute_threshold=config['absolute_threshold'],
|
|
119
120
|
min_matches=config['min_matches'],
|
|
120
121
|
damp=config['damp'],
|
|
122
|
+
regularization_weight=config['regularization_weight_solver_affine'],
|
|
121
123
|
max_iterations=config['max_iterations'],
|
|
122
124
|
max_allowed_error=config['max_allowed_error'],
|
|
123
125
|
max_plateauwidth=config['max_plateauwidth'],
|
|
@@ -135,6 +137,7 @@ solver_split_affine = Solver(
|
|
|
135
137
|
absolute_threshold=config['absolute_threshold'],
|
|
136
138
|
min_matches=config['min_matches'],
|
|
137
139
|
damp=config['damp'],
|
|
140
|
+
regularization_weight=config['regularization_weight_solver_split_affine'],
|
|
138
141
|
max_iterations=config['max_iterations'],
|
|
139
142
|
max_allowed_error=config['max_allowed_error'],
|
|
140
143
|
max_plateauwidth=config['max_plateauwidth'],
|
|
@@ -157,11 +160,11 @@ split_dataset = SplitDataset(
|
|
|
157
160
|
)
|
|
158
161
|
|
|
159
162
|
# -- ALIGNMENT PIPELINE --
|
|
160
|
-
|
|
161
|
-
|
|
163
|
+
interest_point_detection.run()
|
|
164
|
+
interest_point_matching_rigid.run()
|
|
162
165
|
solver_rigid.run()
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
166
|
+
interest_point_matching_affine.run()
|
|
167
|
+
solver_affine.run()
|
|
168
|
+
split_dataset.run()
|
|
169
|
+
interest_point_matching_split_affine.run()
|
|
170
|
+
solver_split_affine.run()
|
Rhapso/pipelines/ray/solver.py
CHANGED
|
@@ -16,7 +16,8 @@ This class implements the Solver pipeline for rigid, affine, and split-affine op
|
|
|
16
16
|
|
|
17
17
|
class Solver:
|
|
18
18
|
def __init__(self, xml_file_path_output, n5_input_path, xml_file_path, run_type, relative_threshold, absolute_threshold,
|
|
19
|
-
min_matches, damp, max_iterations, max_allowed_error, max_plateauwidth, metrics_output_path,
|
|
19
|
+
min_matches, damp, regularization_weight, max_iterations, max_allowed_error, max_plateauwidth, metrics_output_path,
|
|
20
|
+
fixed_tile):
|
|
20
21
|
self.xml_file_path_output = xml_file_path_output
|
|
21
22
|
self.n5_input_path = n5_input_path
|
|
22
23
|
self.xml_file_path = xml_file_path
|
|
@@ -25,6 +26,7 @@ class Solver:
|
|
|
25
26
|
self.absolute_threshold = absolute_threshold
|
|
26
27
|
self.min_matches = min_matches
|
|
27
28
|
self.damp = damp
|
|
29
|
+
self.regularization_weight = regularization_weight
|
|
28
30
|
self.max_iterations = max_iterations
|
|
29
31
|
self.max_allowed_error = max_allowed_error
|
|
30
32
|
self.max_plateauwidth = max_plateauwidth
|
|
@@ -79,7 +81,8 @@ class Solver:
|
|
|
79
81
|
|
|
80
82
|
# Update all points with transform models and iterate through all tiles (views) and optimize alignment
|
|
81
83
|
global_optimization = GlobalOptimization(tc, self.relative_threshold, self.absolute_threshold, self.min_matches, self.damp,
|
|
82
|
-
|
|
84
|
+
self.regularization_weight, self.max_iterations, self.max_allowed_error,
|
|
85
|
+
self.max_plateauwidth, self.run_type, self.metrics_output_path)
|
|
83
86
|
tiles, validation_stats = global_optimization.run()
|
|
84
87
|
print("Global optimization complete")
|
|
85
88
|
|
|
@@ -102,7 +105,8 @@ class Solver:
|
|
|
102
105
|
|
|
103
106
|
# Update all points with transform models and iterate through all tiles (views) and optimize alignment
|
|
104
107
|
global_optimization = GlobalOptimization(tc, self.relative_threshold, self.absolute_threshold, self.min_matches, self.damp,
|
|
105
|
-
self.
|
|
108
|
+
self.regularization_weight, self.max_iterations, self.max_allowed_error,
|
|
109
|
+
self.max_plateauwidth, self.run_type, self.metrics_output_path)
|
|
106
110
|
tiles_round_2, validation_stats_round_2 = global_optimization.run()
|
|
107
111
|
print("Global optimization complete")
|
|
108
112
|
|
|
@@ -7,13 +7,14 @@ GlobalOptimization iteratively refines per-tile transforms to achieve sub-pixel
|
|
|
7
7
|
"""
|
|
8
8
|
|
|
9
9
|
class GlobalOptimization:
|
|
10
|
-
def __init__(self, tiles, relative_threshold, absolute_threshold, min_matches,
|
|
11
|
-
|
|
10
|
+
def __init__(self, tiles, relative_threshold, absolute_threshold, min_matches, damp, regularization_weight,
|
|
11
|
+
max_iterations, max_allowed_error, max_plateauwidth, run_type, metrics_output_path):
|
|
12
12
|
self.tiles = tiles
|
|
13
13
|
self.relative_threshold = relative_threshold
|
|
14
14
|
self.absolute_threshold = absolute_threshold
|
|
15
15
|
self.min_matches = min_matches
|
|
16
16
|
self.damp = damp
|
|
17
|
+
self.regularization_weight = regularization_weight
|
|
17
18
|
self.max_iterations = max_iterations
|
|
18
19
|
self.max_allowed_error = max_allowed_error
|
|
19
20
|
self.max_plateauwidth = max_plateauwidth
|
|
@@ -307,8 +308,7 @@ class GlobalOptimization:
|
|
|
307
308
|
return affine_model
|
|
308
309
|
|
|
309
310
|
def regularize_models(self, affine, rigid):
|
|
310
|
-
|
|
311
|
-
l1 = 1.0 - alpha
|
|
311
|
+
l1 = 1.0 - self.regularization_weight
|
|
312
312
|
|
|
313
313
|
def to_array(model):
|
|
314
314
|
return [
|
|
@@ -320,7 +320,7 @@ class GlobalOptimization:
|
|
|
320
320
|
afs = to_array(affine)
|
|
321
321
|
bfs = to_array(rigid)
|
|
322
322
|
|
|
323
|
-
rfs = [l1 * a +
|
|
323
|
+
rfs = [l1 * a + self.regularization_weight * b for a, b in zip(afs, bfs)]
|
|
324
324
|
|
|
325
325
|
keys = [
|
|
326
326
|
'm00', 'm01', 'm02', 'm03',
|