Rhapso 0.1.991__tar.gz → 0.1.993__tar.gz
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-0.1.991 → rhapso-0.1.993}/PKG-INFO +16 -18
- {rhapso-0.1.991 → rhapso-0.1.993}/README.md +13 -12
- {rhapso-0.1.991 → rhapso-0.1.993}/Rhapso/matching/ransac_matching.py +32 -36
- {rhapso-0.1.991 → rhapso-0.1.993}/Rhapso/pipelines/ray/aws/alignment_pipeline.py +17 -14
- {rhapso-0.1.991 → rhapso-0.1.993}/Rhapso/pipelines/ray/interest_point_matching.py +9 -9
- {rhapso-0.1.991 → rhapso-0.1.993}/Rhapso/pipelines/ray/local/alignment_pipeline.py +20 -17
- {rhapso-0.1.991 → rhapso-0.1.993}/Rhapso/pipelines/ray/solver.py +7 -3
- {rhapso-0.1.991 → rhapso-0.1.993}/Rhapso/solver/global_optimization.py +5 -5
- rhapso-0.1.993/Rhapso/split_dataset/save_xml.py +774 -0
- {rhapso-0.1.991 → rhapso-0.1.993}/Rhapso.egg-info/PKG-INFO +16 -18
- {rhapso-0.1.991 → rhapso-0.1.993}/Rhapso.egg-info/requires.txt +1 -0
- {rhapso-0.1.991 → rhapso-0.1.993}/setup.py +6 -7
- rhapso-0.1.991/Rhapso/split_dataset/save_xml.py +0 -377
- {rhapso-0.1.991 → rhapso-0.1.993}/LICENSE +0 -0
- {rhapso-0.1.991 → rhapso-0.1.993}/Rhapso/__init__.py +0 -0
- {rhapso-0.1.991 → rhapso-0.1.993}/Rhapso/data_prep/__init__.py +0 -0
- {rhapso-0.1.991 → rhapso-0.1.993}/Rhapso/data_prep/n5_reader.py +0 -0
- {rhapso-0.1.991 → rhapso-0.1.993}/Rhapso/data_prep/s3_big_stitcher_reader.py +0 -0
- {rhapso-0.1.991 → rhapso-0.1.993}/Rhapso/data_prep/xml_to_dataframe.py +0 -0
- {rhapso-0.1.991 → rhapso-0.1.993}/Rhapso/detection/__init__.py +0 -0
- {rhapso-0.1.991 → rhapso-0.1.993}/Rhapso/detection/advanced_refinement.py +0 -0
- {rhapso-0.1.991 → rhapso-0.1.993}/Rhapso/detection/difference_of_gaussian.py +0 -0
- {rhapso-0.1.991 → rhapso-0.1.993}/Rhapso/detection/image_reader.py +0 -0
- {rhapso-0.1.991 → rhapso-0.1.993}/Rhapso/detection/metadata_builder.py +0 -0
- {rhapso-0.1.991 → rhapso-0.1.993}/Rhapso/detection/overlap_detection.py +0 -0
- {rhapso-0.1.991 → rhapso-0.1.993}/Rhapso/detection/points_validation.py +0 -0
- {rhapso-0.1.991 → rhapso-0.1.993}/Rhapso/detection/save_interest_points.py +0 -0
- {rhapso-0.1.991 → rhapso-0.1.993}/Rhapso/detection/view_transform_models.py +0 -0
- {rhapso-0.1.991 → rhapso-0.1.993}/Rhapso/fusion/__init__.py +0 -0
- {rhapso-0.1.991 → rhapso-0.1.993}/Rhapso/fusion/affine_fusion/__init__.py +0 -0
- {rhapso-0.1.991 → rhapso-0.1.993}/Rhapso/fusion/affine_fusion/blend.py +0 -0
- {rhapso-0.1.991 → rhapso-0.1.993}/Rhapso/fusion/affine_fusion/fusion.py +0 -0
- {rhapso-0.1.991 → rhapso-0.1.993}/Rhapso/fusion/affine_fusion/geometry.py +0 -0
- {rhapso-0.1.991 → rhapso-0.1.993}/Rhapso/fusion/affine_fusion/io.py +0 -0
- {rhapso-0.1.991 → rhapso-0.1.993}/Rhapso/fusion/affine_fusion/script_utils.py +0 -0
- {rhapso-0.1.991 → rhapso-0.1.993}/Rhapso/fusion/affine_fusion/setup.py +0 -0
- {rhapso-0.1.991 → rhapso-0.1.993}/Rhapso/fusion/affine_fusion_worker.py +0 -0
- {rhapso-0.1.991 → rhapso-0.1.993}/Rhapso/fusion/multiscale/__init__.py +0 -0
- {rhapso-0.1.991 → rhapso-0.1.993}/Rhapso/fusion/multiscale/aind_hcr_data_transformation/__init__.py +0 -0
- {rhapso-0.1.991 → rhapso-0.1.993}/Rhapso/fusion/multiscale/aind_hcr_data_transformation/compress/__init__.py +0 -0
- {rhapso-0.1.991 → rhapso-0.1.993}/Rhapso/fusion/multiscale/aind_hcr_data_transformation/compress/czi_to_zarr.py +0 -0
- {rhapso-0.1.991 → rhapso-0.1.993}/Rhapso/fusion/multiscale/aind_hcr_data_transformation/compress/zarr_writer.py +0 -0
- {rhapso-0.1.991 → rhapso-0.1.993}/Rhapso/fusion/multiscale/aind_hcr_data_transformation/models.py +0 -0
- {rhapso-0.1.991 → rhapso-0.1.993}/Rhapso/fusion/multiscale/aind_hcr_data_transformation/utils/__init__.py +0 -0
- {rhapso-0.1.991 → rhapso-0.1.993}/Rhapso/fusion/multiscale/aind_hcr_data_transformation/utils/utils.py +0 -0
- {rhapso-0.1.991 → rhapso-0.1.993}/Rhapso/fusion/multiscale/aind_hcr_data_transformation/zeiss_job.py +0 -0
- {rhapso-0.1.991 → rhapso-0.1.993}/Rhapso/fusion/multiscale/aind_z1_radial_correction/__init__.py +0 -0
- {rhapso-0.1.991 → rhapso-0.1.993}/Rhapso/fusion/multiscale/aind_z1_radial_correction/array_to_zarr.py +0 -0
- {rhapso-0.1.991 → rhapso-0.1.993}/Rhapso/fusion/multiscale/aind_z1_radial_correction/radial_correction.py +0 -0
- {rhapso-0.1.991 → rhapso-0.1.993}/Rhapso/fusion/multiscale/aind_z1_radial_correction/run_capsule.py +0 -0
- {rhapso-0.1.991 → rhapso-0.1.993}/Rhapso/fusion/multiscale/aind_z1_radial_correction/utils/__init__.py +0 -0
- {rhapso-0.1.991 → rhapso-0.1.993}/Rhapso/fusion/multiscale/aind_z1_radial_correction/utils/utils.py +0 -0
- {rhapso-0.1.991 → rhapso-0.1.993}/Rhapso/fusion/multiscale/aind_z1_radial_correction/worker.py +0 -0
- {rhapso-0.1.991 → rhapso-0.1.993}/Rhapso/fusion/multiscale_worker.py +0 -0
- {rhapso-0.1.991 → rhapso-0.1.993}/Rhapso/fusion/neuroglancer_link_gen/__init__.py +0 -0
- {rhapso-0.1.991 → rhapso-0.1.993}/Rhapso/fusion/neuroglancer_link_gen/dispim_link.py +0 -0
- {rhapso-0.1.991 → rhapso-0.1.993}/Rhapso/fusion/neuroglancer_link_gen/exaspim_link.py +0 -0
- {rhapso-0.1.991 → rhapso-0.1.993}/Rhapso/fusion/neuroglancer_link_gen/hcr_link.py +0 -0
- {rhapso-0.1.991 → rhapso-0.1.993}/Rhapso/fusion/neuroglancer_link_gen/iSPIM_top.py +0 -0
- {rhapso-0.1.991 → rhapso-0.1.993}/Rhapso/fusion/neuroglancer_link_gen/link_utils.py +0 -0
- {rhapso-0.1.991 → rhapso-0.1.993}/Rhapso/fusion/neuroglancer_link_gen/main.py +0 -0
- {rhapso-0.1.991 → rhapso-0.1.993}/Rhapso/fusion/neuroglancer_link_gen/ng_layer.py +0 -0
- {rhapso-0.1.991 → rhapso-0.1.993}/Rhapso/fusion/neuroglancer_link_gen/ng_state.py +0 -0
- {rhapso-0.1.991 → rhapso-0.1.993}/Rhapso/fusion/neuroglancer_link_gen/parsers.py +0 -0
- {rhapso-0.1.991 → rhapso-0.1.993}/Rhapso/fusion/neuroglancer_link_gen/raw_link.py +0 -0
- {rhapso-0.1.991 → rhapso-0.1.993}/Rhapso/fusion/neuroglancer_link_gen/utils/__init__.py +0 -0
- {rhapso-0.1.991 → rhapso-0.1.993}/Rhapso/fusion/neuroglancer_link_gen/utils/shader_utils.py +0 -0
- {rhapso-0.1.991 → rhapso-0.1.993}/Rhapso/fusion/neuroglancer_link_gen/utils/transfer.py +0 -0
- {rhapso-0.1.991 → rhapso-0.1.993}/Rhapso/fusion/neuroglancer_link_gen/utils/utils.py +0 -0
- {rhapso-0.1.991 → rhapso-0.1.993}/Rhapso/fusion/neuroglancer_link_gen_worker.py +0 -0
- {rhapso-0.1.991 → rhapso-0.1.993}/Rhapso/matching/__init__.py +0 -0
- {rhapso-0.1.991 → rhapso-0.1.993}/Rhapso/matching/load_and_transform_points.py +0 -0
- {rhapso-0.1.991 → rhapso-0.1.993}/Rhapso/matching/save_matches.py +0 -0
- {rhapso-0.1.991 → rhapso-0.1.993}/Rhapso/matching/xml_parser.py +0 -0
- {rhapso-0.1.991 → rhapso-0.1.993}/Rhapso/pipelines/__init__.py +0 -0
- {rhapso-0.1.991 → rhapso-0.1.993}/Rhapso/pipelines/ray/__init__.py +0 -0
- {rhapso-0.1.991 → rhapso-0.1.993}/Rhapso/pipelines/ray/aws/__init__.py +0 -0
- {rhapso-0.1.991 → rhapso-0.1.993}/Rhapso/pipelines/ray/aws/config/__init__.py +0 -0
- {rhapso-0.1.991 → rhapso-0.1.993}/Rhapso/pipelines/ray/evaluation.py +0 -0
- {rhapso-0.1.991 → rhapso-0.1.993}/Rhapso/pipelines/ray/interest_point_detection.py +0 -0
- {rhapso-0.1.991 → rhapso-0.1.993}/Rhapso/pipelines/ray/local/__init__.py +0 -0
- {rhapso-0.1.991 → rhapso-0.1.993}/Rhapso/pipelines/ray/matching_stats.py +0 -0
- {rhapso-0.1.991 → rhapso-0.1.993}/Rhapso/pipelines/ray/param/__init__.py +0 -0
- {rhapso-0.1.991 → rhapso-0.1.993}/Rhapso/pipelines/ray/split_dataset.py +0 -0
- {rhapso-0.1.991 → rhapso-0.1.993}/Rhapso/solver/__init__.py +0 -0
- {rhapso-0.1.991 → rhapso-0.1.993}/Rhapso/solver/compute_tiles.py +0 -0
- {rhapso-0.1.991 → rhapso-0.1.993}/Rhapso/solver/concatenate_models.py +0 -0
- {rhapso-0.1.991 → rhapso-0.1.993}/Rhapso/solver/connected_graphs.py +0 -0
- {rhapso-0.1.991 → rhapso-0.1.993}/Rhapso/solver/data_prep.py +0 -0
- {rhapso-0.1.991 → rhapso-0.1.993}/Rhapso/solver/model_and_tile_setup.py +0 -0
- {rhapso-0.1.991 → rhapso-0.1.993}/Rhapso/solver/pre_align_tiles.py +0 -0
- {rhapso-0.1.991 → rhapso-0.1.993}/Rhapso/solver/save_results.py +0 -0
- {rhapso-0.1.991 → rhapso-0.1.993}/Rhapso/solver/view_transforms.py +0 -0
- {rhapso-0.1.991 → rhapso-0.1.993}/Rhapso/solver/xml_to_dataframe_solver.py +0 -0
- {rhapso-0.1.991 → rhapso-0.1.993}/Rhapso/split_dataset/__init__.py +0 -0
- {rhapso-0.1.991 → rhapso-0.1.993}/Rhapso/split_dataset/compute_grid_rules.py +0 -0
- {rhapso-0.1.991 → rhapso-0.1.993}/Rhapso/split_dataset/save_points.py +0 -0
- {rhapso-0.1.991 → rhapso-0.1.993}/Rhapso/split_dataset/split_images.py +0 -0
- {rhapso-0.1.991 → rhapso-0.1.993}/Rhapso/split_dataset/xml_to_dataframe_split.py +0 -0
- {rhapso-0.1.991 → rhapso-0.1.993}/Rhapso.egg-info/SOURCES.txt +0 -0
- {rhapso-0.1.991 → rhapso-0.1.993}/Rhapso.egg-info/dependency_links.txt +0 -0
- {rhapso-0.1.991 → rhapso-0.1.993}/Rhapso.egg-info/top_level.txt +0 -0
- {rhapso-0.1.991 → rhapso-0.1.993}/pyproject.toml +0 -0
- {rhapso-0.1.991 → rhapso-0.1.993}/setup.cfg +0 -0
- {rhapso-0.1.991 → rhapso-0.1.993}/tests/__init__.py +0 -0
- {rhapso-0.1.991 → rhapso-0.1.993}/tests/test_detection.py +0 -0
- {rhapso-0.1.991 → rhapso-0.1.993}/tests/test_matching.py +0 -0
- {rhapso-0.1.991 → rhapso-0.1.993}/tests/test_solving.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: Rhapso
|
|
3
|
-
Version: 0.1.
|
|
3
|
+
Version: 0.1.993
|
|
4
4
|
Summary: A python package for aligning and stitching light sheet fluorescence microscopy images
|
|
5
5
|
Author: ND
|
|
6
6
|
Author-email: sean.fite@alleninstitute.org
|
|
@@ -9,13 +9,9 @@ Project-URL: Roadmap, https://github.com/AllenNeuralDynamics/Rhapso/issues
|
|
|
9
9
|
Classifier: Development Status :: 3 - Alpha
|
|
10
10
|
Classifier: Intended Audience :: Developers
|
|
11
11
|
Classifier: Natural Language :: English
|
|
12
|
-
Classifier: Programming Language :: Python :: 3
|
|
13
|
-
Classifier: Programming Language :: Python :: 3.7
|
|
14
|
-
Classifier: Programming Language :: Python :: 3.8
|
|
15
|
-
Classifier: Programming Language :: Python :: 3.9
|
|
16
12
|
Classifier: Programming Language :: Python :: 3.10
|
|
17
13
|
Classifier: Operating System :: OS Independent
|
|
18
|
-
Requires-Python: >=3.
|
|
14
|
+
Requires-Python: >=3.10
|
|
19
15
|
Description-Content-Type: text/markdown
|
|
20
16
|
License-File: LICENSE
|
|
21
17
|
Requires-Dist: pandas
|
|
@@ -33,6 +29,7 @@ Requires-Dist: matplotlib==3.10.0
|
|
|
33
29
|
Requires-Dist: memory-profiler==0.61.0
|
|
34
30
|
Requires-Dist: s3fs==2024.12.0
|
|
35
31
|
Requires-Dist: scikit-learn
|
|
32
|
+
Requires-Dist: click==8.2.1
|
|
36
33
|
Dynamic: author
|
|
37
34
|
Dynamic: author-email
|
|
38
35
|
Dynamic: classifier
|
|
@@ -414,25 +411,26 @@ python Rhapso/pipelines/ray/aws/alignment_pipeline.py
|
|
|
414
411
|
| Parameter | Feature / step | What it does | Typical range |
|
|
415
412
|
| :---------------------------- | :------------------- | :---------------------------------------------------------------- | :------------- |
|
|
416
413
|
| `model_min_matches` | RANSAC | Minimum correspondences to estimate a rigid transform | 18 – 32 |
|
|
417
|
-
| `
|
|
418
|
-
| `
|
|
414
|
+
| `inlier_threshold` | RANSAC | Inlier tolerance scaling; larger = looser inlier threshold | 50 – 100 |
|
|
415
|
+
| `min_inlier_ratio` | RANSAC | Regularization strength during model fitting | 0.1 – 0.05 |
|
|
419
416
|
| `num_iterations` | RANSAC | Number of RANSAC trials; higher = more robust, slower | 10,0000 |
|
|
420
|
-
| `regularization_weight` | RANSAC | Weight applied to the regularization term | 1.0
|
|
417
|
+
| `regularization_weight` | RANSAC | Weight applied to the regularization term | 0.05 - 1.0 |
|
|
421
418
|
|
|
422
419
|
```
|
|
423
420
|
<br>
|
|
424
421
|
|
|
425
422
|
### Solver
|
|
426
423
|
```
|
|
427
|
-
| Parameter
|
|
428
|
-
|
|
|
429
|
-
| `relative_threshold`
|
|
430
|
-
| `absolute_threshold`
|
|
431
|
-
| `min_matches`
|
|
432
|
-
| `damp`
|
|
433
|
-
| `max_iterations`
|
|
434
|
-
| `max_allowed_error`
|
|
435
|
-
| `max_plateauwidth`
|
|
424
|
+
| Parameter | Feature / step | What it does | Typical range |
|
|
425
|
+
| :----------------------- | :------------- | :----------------------------------------------------------------- | :------------------ |
|
|
426
|
+
| `relative_threshold` | Graph pruning | Reject edges with residuals above dataset-relative cutoff | 3.5 |
|
|
427
|
+
| `absolute_threshold` | Graph pruning | Reject edges above an absolute error bound (detection-space units) | 7.0 |
|
|
428
|
+
| `min_matches` | Graph pruning | Minimum matches required to retain an edge between tiles | 3 |
|
|
429
|
+
| `damp` | Optimization | Damping for iterative solver; higher can stabilize tough cases | 1.0 |
|
|
430
|
+
| `max_iterations` | Optimization | Upper bound on solver iterations | 10,0000 |
|
|
431
|
+
| `max_allowed_error` | Optimization | Overall error cap; `inf` disables hard stop by error | `inf` |
|
|
432
|
+
| `max_plateauwidth` | Early stopping | Stagnation window before stopping on no improvement | 200 |
|
|
433
|
+
| `regularization_weight` | RANSAC | Weight applied to the regularization term | 0.05 - 1.0 |
|
|
436
434
|
|
|
437
435
|
```
|
|
438
436
|
|
|
@@ -368,25 +368,26 @@ python Rhapso/pipelines/ray/aws/alignment_pipeline.py
|
|
|
368
368
|
| Parameter | Feature / step | What it does | Typical range |
|
|
369
369
|
| :---------------------------- | :------------------- | :---------------------------------------------------------------- | :------------- |
|
|
370
370
|
| `model_min_matches` | RANSAC | Minimum correspondences to estimate a rigid transform | 18 – 32 |
|
|
371
|
-
| `
|
|
372
|
-
| `
|
|
371
|
+
| `inlier_threshold` | RANSAC | Inlier tolerance scaling; larger = looser inlier threshold | 50 – 100 |
|
|
372
|
+
| `min_inlier_ratio` | RANSAC | Regularization strength during model fitting | 0.1 – 0.05 |
|
|
373
373
|
| `num_iterations` | RANSAC | Number of RANSAC trials; higher = more robust, slower | 10,0000 |
|
|
374
|
-
| `regularization_weight` | RANSAC | Weight applied to the regularization term | 1.0
|
|
374
|
+
| `regularization_weight` | RANSAC | Weight applied to the regularization term | 0.05 - 1.0 |
|
|
375
375
|
|
|
376
376
|
```
|
|
377
377
|
<br>
|
|
378
378
|
|
|
379
379
|
### Solver
|
|
380
380
|
```
|
|
381
|
-
| Parameter
|
|
382
|
-
|
|
|
383
|
-
| `relative_threshold`
|
|
384
|
-
| `absolute_threshold`
|
|
385
|
-
| `min_matches`
|
|
386
|
-
| `damp`
|
|
387
|
-
| `max_iterations`
|
|
388
|
-
| `max_allowed_error`
|
|
389
|
-
| `max_plateauwidth`
|
|
381
|
+
| Parameter | Feature / step | What it does | Typical range |
|
|
382
|
+
| :----------------------- | :------------- | :----------------------------------------------------------------- | :------------------ |
|
|
383
|
+
| `relative_threshold` | Graph pruning | Reject edges with residuals above dataset-relative cutoff | 3.5 |
|
|
384
|
+
| `absolute_threshold` | Graph pruning | Reject edges above an absolute error bound (detection-space units) | 7.0 |
|
|
385
|
+
| `min_matches` | Graph pruning | Minimum matches required to retain an edge between tiles | 3 |
|
|
386
|
+
| `damp` | Optimization | Damping for iterative solver; higher can stabilize tough cases | 1.0 |
|
|
387
|
+
| `max_iterations` | Optimization | Upper bound on solver iterations | 10,0000 |
|
|
388
|
+
| `max_allowed_error` | Optimization | Overall error cap; `inf` disables hard stop by error | `inf` |
|
|
389
|
+
| `max_plateauwidth` | Early stopping | Stagnation window before stopping on no improvement | 200 |
|
|
390
|
+
| `regularization_weight` | RANSAC | Weight applied to the regularization term | 0.05 - 1.0 |
|
|
390
391
|
|
|
391
392
|
```
|
|
392
393
|
|
|
@@ -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()
|
|
@@ -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',
|