Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 4 additions & 13 deletions perception/hashers/tools.py
Original file line number Diff line number Diff line change
Expand Up @@ -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]
Expand All @@ -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.
Expand Down Expand Up @@ -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(
Expand Down Expand Up @@ -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.
"""
Expand Down
9 changes: 4 additions & 5 deletions perception/local_descriptor_deduplication.py
Original file line number Diff line number Diff line change
Expand Up @@ -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(
Expand Down Expand Up @@ -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)

Expand Down
29 changes: 14 additions & 15 deletions tests/test_tools.py
Original file line number Diff line number Diff line change
Expand Up @@ -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"),
Expand Down Expand Up @@ -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)
Expand Down Expand Up @@ -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():
Expand All @@ -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}"


Expand Down