Skip to content

Commit da14e49

Browse files
Fix --affine CLI parameter (#244)
* Fix --affine CLI parameter * add tests and validations for the fix so this can no happen unintentionally again * make all too long errors and warnings one liner. Line breaks mess up with tests and are not nice for the user --------- Co-authored-by: Lukas Weber <l.alex.w@web.de>
1 parent a471af1 commit da14e49

7 files changed

Lines changed: 48 additions & 17 deletions

File tree

stitching/cli/stitch.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,8 @@ def create_parser():
4646
"--affine",
4747
action="store_true",
4848
help="Overwrites multiple parameters to optimize the stitching for "
49-
"scans and images captured by specialized devices.",
49+
"scans and images captured by specialized devices. The follwing parameters "
50+
"are set: " + str(AffineStitcher.AFFINE_DEFAULTS),
5051
)
5152
parser.add_argument(
5253
"--medium_megapix",
@@ -315,6 +316,7 @@ def main():
315316
affine_mode = args_dict.pop("affine")
316317

317318
if affine_mode:
319+
args_dict.update(AffineStitcher.AFFINE_DEFAULTS)
318320
stitcher = AffineStitcher(**args_dict)
319321
else:
320322
stitcher = Stitcher(**args_dict)

stitching/cropper.py

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -95,9 +95,7 @@ def estimate_largest_interior_rectangle(self, mask):
9595
contours, hierarchy = cv.findContours(mask, cv.RETR_TREE, cv.CHAIN_APPROX_NONE)
9696
if not hierarchy.shape == (1, 1, 4) or not np.all(hierarchy == -1):
9797
raise StitchingError(
98-
"""Invalid Contour. Run with --no-crop (using the stitch interface),
99-
crop=false (using the stitcher class) or Cropper(False)
100-
(using the cropper class)"""
98+
"Invalid Contour. Run with --no-crop (using the stitch interface), crop=false (using the stitcher class) or Cropper(False) (using the cropper class)" # noqa: E501
10199
)
102100
contour = contours[0][:, 0, :]
103101

stitching/seam_finder.py

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -98,8 +98,7 @@ def blend_seam_masks(
9898
def colored_img_generator(sizes, colors):
9999
if len(sizes) + 1 > len(colors):
100100
warnings.warn(
101-
"""Without additional colors,
102-
there will be seam masks with identical colors""",
101+
"Without additional colors, there will be seam masks with identical colors", # noqa: E501
103102
StitchingWarning,
104103
)
105104

stitching/stitcher.py

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import warnings
12
from types import SimpleNamespace
23

34
from .blender import Blender
@@ -10,7 +11,7 @@
1011
from .feature_matcher import FeatureMatcher
1112
from .images import Images
1213
from .seam_finder import SeamFinder
13-
from .stitching_error import StitchingError
14+
from .stitching_error import StitchingError, StitchingWarning
1415
from .subsetter import Subsetter
1516
from .timelapser import Timelapser
1617
from .verbose import verbose_stitching
@@ -275,3 +276,12 @@ class AffineStitcher(Stitcher):
275276

276277
DEFAULT_SETTINGS = Stitcher.DEFAULT_SETTINGS.copy()
277278
DEFAULT_SETTINGS.update(AFFINE_DEFAULTS)
279+
280+
def initialize_stitcher(self, **kwargs):
281+
for key, value in kwargs.items():
282+
if key in self.AFFINE_DEFAULTS and value != self.AFFINE_DEFAULTS[key]:
283+
warnings.warn(
284+
f"You are overwriting an affine default ({key}={self.AFFINE_DEFAULTS[key]}) with another value ({value}). Make sure this is intended", # noqa: E501
285+
StitchingWarning,
286+
)
287+
super().initialize_stitcher(**kwargs)

stitching/subsetter.py

Lines changed: 2 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -30,11 +30,7 @@ def subset(self, img_names, features, matches):
3030

3131
if len(indices) < len(img_names):
3232
warnings.warn(
33-
"""Not all images are included in the final panorama.
34-
If this is not intended, use the 'matches_graph_dot_file'
35-
parameter to analyze your matches. You might want to
36-
lower the 'confidence_threshold' or try another 'detector'
37-
to include all your images.""",
33+
"Not all images are included in the final panorama. If this is not intended, use the 'matches_graph_dot_file' parameter to analyze your matches. You might want to lower the 'confidence_threshold' or try another 'detector' to include all your images.", # noqa: E501
3834
StitchingWarning,
3935
)
4036

@@ -66,11 +62,7 @@ def get_indices_to_keep(self, features, pairwise_matches):
6662

6763
if len(indices) < 2:
6864
raise StitchingError(
69-
"""No match exceeds the given confidence threshold.
70-
Do your images have enough overlap and common
71-
features? If yes, you might want to lower the
72-
'confidence_threshold' or try another
73-
'detector'."""
65+
"No match exceeds the given confidence threshold. Do your images have enough overlap and common features? If yes, you might want to lower the 'confidence_threshold' or try another 'detector'." # noqa: E501
7466
)
7567

7668
return indices

tests/test_stitch_cli.py

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,27 @@ def test_main_verbose(self):
5858
img.shape[:2], (150, 590), atol=max_image_shape_derivation
5959
)
6060

61+
def test_main_affine(self):
62+
output = test_output("budapest_from_cli.jpg")
63+
test_args = [
64+
"stitch.py",
65+
test_input("budapest?.jpg"),
66+
"--affine",
67+
"--detector",
68+
"sift",
69+
"--no-crop",
70+
"--output",
71+
output,
72+
]
73+
with patch.object(sys, "argv", test_args):
74+
main()
75+
76+
img = cv.imread(output)
77+
max_image_shape_derivation = 50
78+
np.testing.assert_allclose(
79+
img.shape[:2], (1155, 2310), atol=max_image_shape_derivation
80+
)
81+
6182
def test_main_feature_masks(self):
6283
output = test_output("features_with_mask_from_cli.jpg")
6384
test_args = [

tests/test_stitcher.py

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -161,6 +161,15 @@ def test_stitcher_boat_aquaduct_subset(self):
161161
graph_content = file.read()
162162
self.assertTrue(graph_content.startswith("graph matches_graph{"))
163163

164+
def test_affine_stitcher_warning(self):
165+
with self.assertWarns(StitchingWarning) as cm:
166+
AffineStitcher(estimator="homography")
167+
self.assertTrue(
168+
str(cm.warning).startswith(
169+
"You are overwriting an affine default (estimator=affine)"
170+
)
171+
)
172+
164173
def test_affine_stitcher_budapest(self):
165174
settings = {
166175
"detector": "sift",

0 commit comments

Comments
 (0)