diff --git a/stitching/cli/stitch.py b/stitching/cli/stitch.py index ada8833..5ef19b2 100644 --- a/stitching/cli/stitch.py +++ b/stitching/cli/stitch.py @@ -46,7 +46,8 @@ def create_parser(): "--affine", action="store_true", help="Overwrites multiple parameters to optimize the stitching for " - "scans and images captured by specialized devices.", + "scans and images captured by specialized devices. The follwing parameters " + "are set: " + str(AffineStitcher.AFFINE_DEFAULTS), ) parser.add_argument( "--medium_megapix", @@ -315,6 +316,7 @@ def main(): affine_mode = args_dict.pop("affine") if affine_mode: + args_dict.update(AffineStitcher.AFFINE_DEFAULTS) stitcher = AffineStitcher(**args_dict) else: stitcher = Stitcher(**args_dict) diff --git a/stitching/cropper.py b/stitching/cropper.py index 4d8d71b..4668f9a 100644 --- a/stitching/cropper.py +++ b/stitching/cropper.py @@ -95,9 +95,7 @@ def estimate_largest_interior_rectangle(self, mask): contours, hierarchy = cv.findContours(mask, cv.RETR_TREE, cv.CHAIN_APPROX_NONE) if not hierarchy.shape == (1, 1, 4) or not np.all(hierarchy == -1): raise StitchingError( - """Invalid Contour. Run with --no-crop (using the stitch interface), - crop=false (using the stitcher class) or Cropper(False) - (using the cropper class)""" + "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 ) contour = contours[0][:, 0, :] diff --git a/stitching/seam_finder.py b/stitching/seam_finder.py index 1d60926..637e472 100644 --- a/stitching/seam_finder.py +++ b/stitching/seam_finder.py @@ -98,8 +98,7 @@ def blend_seam_masks( def colored_img_generator(sizes, colors): if len(sizes) + 1 > len(colors): warnings.warn( - """Without additional colors, - there will be seam masks with identical colors""", + "Without additional colors, there will be seam masks with identical colors", # noqa: E501 StitchingWarning, ) diff --git a/stitching/stitcher.py b/stitching/stitcher.py index 470f6b1..fd45513 100644 --- a/stitching/stitcher.py +++ b/stitching/stitcher.py @@ -1,3 +1,4 @@ +import warnings from types import SimpleNamespace from .blender import Blender @@ -10,7 +11,7 @@ from .feature_matcher import FeatureMatcher from .images import Images from .seam_finder import SeamFinder -from .stitching_error import StitchingError +from .stitching_error import StitchingError, StitchingWarning from .subsetter import Subsetter from .timelapser import Timelapser from .verbose import verbose_stitching @@ -275,3 +276,12 @@ class AffineStitcher(Stitcher): DEFAULT_SETTINGS = Stitcher.DEFAULT_SETTINGS.copy() DEFAULT_SETTINGS.update(AFFINE_DEFAULTS) + + def initialize_stitcher(self, **kwargs): + for key, value in kwargs.items(): + if key in self.AFFINE_DEFAULTS and value != self.AFFINE_DEFAULTS[key]: + warnings.warn( + f"You are overwriting an affine default ({key}={self.AFFINE_DEFAULTS[key]}) with another value ({value}). Make sure this is intended", # noqa: E501 + StitchingWarning, + ) + super().initialize_stitcher(**kwargs) diff --git a/stitching/subsetter.py b/stitching/subsetter.py index 08e46b1..d56ae31 100644 --- a/stitching/subsetter.py +++ b/stitching/subsetter.py @@ -30,11 +30,7 @@ def subset(self, img_names, features, matches): if len(indices) < len(img_names): warnings.warn( - """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.""", + "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 StitchingWarning, ) @@ -66,11 +62,7 @@ def get_indices_to_keep(self, features, pairwise_matches): if len(indices) < 2: raise StitchingError( - """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'.""" + "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 ) return indices diff --git a/tests/test_stitch_cli.py b/tests/test_stitch_cli.py index 923807b..443d60f 100644 --- a/tests/test_stitch_cli.py +++ b/tests/test_stitch_cli.py @@ -58,6 +58,27 @@ def test_main_verbose(self): img.shape[:2], (150, 590), atol=max_image_shape_derivation ) + def test_main_affine(self): + output = test_output("budapest_from_cli.jpg") + test_args = [ + "stitch.py", + test_input("budapest?.jpg"), + "--affine", + "--detector", + "sift", + "--no-crop", + "--output", + output, + ] + with patch.object(sys, "argv", test_args): + main() + + img = cv.imread(output) + max_image_shape_derivation = 50 + np.testing.assert_allclose( + img.shape[:2], (1155, 2310), atol=max_image_shape_derivation + ) + def test_main_feature_masks(self): output = test_output("features_with_mask_from_cli.jpg") test_args = [ diff --git a/tests/test_stitcher.py b/tests/test_stitcher.py index aa16606..6869fb2 100644 --- a/tests/test_stitcher.py +++ b/tests/test_stitcher.py @@ -161,6 +161,15 @@ def test_stitcher_boat_aquaduct_subset(self): graph_content = file.read() self.assertTrue(graph_content.startswith("graph matches_graph{")) + def test_affine_stitcher_warning(self): + with self.assertWarns(StitchingWarning) as cm: + AffineStitcher(estimator="homography") + self.assertTrue( + str(cm.warning).startswith( + "You are overwriting an affine default (estimator=affine)" + ) + ) + def test_affine_stitcher_budapest(self): settings = { "detector": "sift",