diff --git a/perception/hashers/tools.py b/perception/hashers/tools.py index 0414859..ff76d64 100644 --- a/perception/hashers/tools.py +++ b/perception/hashers/tools.py @@ -1064,10 +1064,7 @@ def unletterbox( if len(set(corners)) == 4: LOGGER.debug("No common corner color detected, skipping content detection.") - return ( - (0, w), - (0, h), - ) # Return full image bounds instead of None to maintain backwards compatibility + return None # Use the most common corner value as the background intensity. counts = Counter(corners) bg_gray = counts.most_common(1)[0][0] @@ -1079,10 +1076,7 @@ def unletterbox( # If every pixel is classified as content, there is no border to remove. if content_mask.all(): LOGGER.debug("All pixels differ from background; no letterbox detected.") - return ( - (0, w), - (0, h), - ) # Return full image bounds instead of None to maintain backwards compatibility + return None # Find the content bounding box by projecting the mask onto rows and # columns. cv2.reduce is used instead of np.sum for performance. @@ -1116,10 +1110,7 @@ def unletterbox( "Crop would not reduce either dimension by %.0f%%; skipping.", min_reduction * 100, ) - return ( - (0, w), - (0, h), - ) # Return full image bounds instead of None to maintain backwards compatibility + return None # Reject if the remaining content region is too small to be useful. if width < min_side_length or height < min_side_length: LOGGER.debug( @@ -1156,7 +1147,7 @@ def unletterbox_crop( min_reduction: The minimum fraction (0–1) of the original width or height that must be removed for the crop to be worthwhile. If the crop removes less than this from both dimensions, - the original image is returned. Defaults to 0.02 (2%). + ``None`` is returned. Defaults to 0.02 (2%). Returns: The cropped image or None if the image is mostly blank space. """ diff --git a/perception/local_descriptor_deduplication.py b/perception/local_descriptor_deduplication.py index fbacc2e..639d14e 100644 --- a/perception/local_descriptor_deduplication.py +++ b/perception/local_descriptor_deduplication.py @@ -157,7 +157,7 @@ def validate_match( descriptorB["descriptors"].astype("float32"), 2 ) good_A2B, good_B2A = map( - lambda distances: (distances[:, 0] < distances[:, 1] * self.ratio), + lambda distances: distances[:, 0] < distances[:, 1] * self.ratio, [distances_A2B, distances_B2A], ) match = min( @@ -289,10 +289,9 @@ def load_and_preprocess(filepath, max_size=DEFAULT_MAX_SIZE, grayscale=True): LOGGER.warning("Failed to load image %s", filepath) return None res = pht.unletterbox(image) - if res is None: - return None - (x1, x2), (y1, y2) = res - image = np.ascontiguousarray(image[y1:y2, x1:x2]) + if res is not None: + (x1, x2), (y1, y2) = res + image = np.ascontiguousarray(image[y1:y2, x1:x2]) if grayscale: image = cv2.cvtColor(image, cv2.COLOR_RGB2GRAY) diff --git a/tests/test_tools.py b/tests/test_tools.py index 7d73372..cb9681c 100644 --- a/tests/test_tools.py +++ b/tests/test_tools.py @@ -106,7 +106,14 @@ def test_compute_euclidean_pairwise_duplicates(): # Use grouped files. counts = np.array([3, 3, 2, 2]) expected = np.array( - [[2 / 3, 2 / 3], [0, 0], [0, 0], [1 / 3, 1 / 2], [0, 0], [0, 0]] + [ + [2 / 3, 2 / 3], + [0, 0], + [0, 0], + [1 / 3, 1 / 2], + [0, 0], + [0, 0], + ] ) actual = tools.extensions.compute_euclidean_pairwise_duplicates( X=X.astype("int32"), @@ -206,12 +213,7 @@ def test_unletterbox_color(): padded[50 : 50 + image.shape[0], 25 : 25 + image.shape[1]] = image # Should not unletterbox since not black. results = hashers.tools.unletterbox(padded, only_remove_black=True) - assert results is not None - (x1, x2), (y1, y2) = results - assert y1 == 0 - assert y2 == padded.shape[0] - assert x1 == 0 - assert x2 == padded.shape[1] + assert results is None # Should unletterbox color: results = hashers.tools.unletterbox(padded, only_remove_black=False) @@ -252,12 +254,7 @@ def test_unletterbox_noblackbars(): image = hashers.tools.read(testing.DEFAULT_TEST_IMAGES[0]) results = hashers.tools.unletterbox(image) - assert results is not None - (x1, x2), (y1, y2) = results - assert x1 == 0 - assert y1 == 0 - assert x2 == image.shape[1] - assert y2 == image.shape[0] + assert results is None def test_ffmpeg_video(): @@ -278,8 +275,10 @@ def test_ffmpeg_video(): diff = np.abs(frame1.astype("int32") - frame2.astype("int32")).flatten() assert index1 == index2, f"Index mismatch for {filename}" np.testing.assert_allclose( - timestamp1, timestamp2 - ), f"Timestamp mismatch for {filename}" + timestamp1, + timestamp2, + err_msg=f"Timestamp mismatch for {filename}", + ) assert np.percentile(diff, 75) < 25, f"Frame mismatch for {filename}"