US01-04: Detect and Decide Duplicates (#49)
This commit was merged in pull request #49.
This commit is contained in:
52
tests/unit/test_phash.py
Normal file
52
tests/unit/test_phash.py
Normal file
@@ -0,0 +1,52 @@
|
||||
"""Golden perceptual-hash relationships and confidence bands."""
|
||||
|
||||
import numpy as np
|
||||
from PIL import Image
|
||||
|
||||
from photo_pipeline.services import hashing
|
||||
from photo_pipeline.services.duplicates import NEAR_MAX, SIMILAR_MAX
|
||||
|
||||
|
||||
def _structured(path, seed, size=(256, 192)):
|
||||
rng = np.random.default_rng(seed)
|
||||
w, h = size
|
||||
base = np.zeros((h, w, 3), dtype=np.uint8)
|
||||
for _ in range(6):
|
||||
x0 = int(rng.integers(0, w - 60))
|
||||
y0 = int(rng.integers(0, h - 60))
|
||||
base[y0 : y0 + 60, x0 : x0 + 60] = rng.integers(0, 256, 3)
|
||||
grad = np.linspace(0, 120, w, dtype=np.uint8)
|
||||
base[:, :, 0] = np.clip(base[:, :, 0].astype(int) + grad[None, :], 0, 255)
|
||||
Image.fromarray(base).save(path, quality=95)
|
||||
return path
|
||||
|
||||
|
||||
def test_phash_is_16_hex_chars(tmp_path):
|
||||
value = hashing.phash(_structured(tmp_path / "a.jpg", 1))
|
||||
assert len(value) == 16
|
||||
int(value, 16) # parses as hex
|
||||
|
||||
|
||||
def test_identical_pixels_have_zero_distance(tmp_path):
|
||||
a = _structured(tmp_path / "a.jpg", 1)
|
||||
assert hashing.phash_distance(hashing.phash(a), hashing.phash(a)) == 0
|
||||
|
||||
|
||||
def test_resized_copy_stays_within_near_band(tmp_path):
|
||||
a = _structured(tmp_path / "a.jpg", 1)
|
||||
small = tmp_path / "a_small.jpg"
|
||||
with Image.open(a) as image:
|
||||
image.resize((image.width // 2, image.height // 2), Image.LANCZOS).save(small, quality=95)
|
||||
distance = hashing.phash_distance(hashing.phash(a), hashing.phash(small))
|
||||
assert distance <= NEAR_MAX
|
||||
|
||||
|
||||
def test_distinct_images_exceed_similar_band(tmp_path):
|
||||
a = _structured(tmp_path / "a.jpg", 1)
|
||||
b = _structured(tmp_path / "b.jpg", 2)
|
||||
distance = hashing.phash_distance(hashing.phash(a), hashing.phash(b))
|
||||
assert distance > SIMILAR_MAX
|
||||
|
||||
|
||||
def test_phash_is_versioned():
|
||||
assert hashing.PHASH_VERSION >= 1
|
||||
Reference in New Issue
Block a user