Spaces:
Running on Zero
Running on Zero
Download tests/test_image_utils.py from maxmcd/Selectable-Face-Swap: direct link, hf CLI and curl.
- Browser
- Download file 7.24 kB
-
https://huggingface.co/spaces/maxmcd/Selectable-Face-Swap/resolve/main/tests/test_image_utils.py
- Command line
-
hf download hf://spaces/maxmcd/Selectable-Face-Swap/tests/test_image_utils.py
-
curl -L -o test_image_utils.py https://huggingface.co/spaces/maxmcd/Selectable-Face-Swap/resolve/main/tests/test_image_utils.py
7.24 kB
| import base64 | |
| import sys | |
| from io import BytesIO | |
| from unittest.mock import MagicMock | |
| import numpy as np | |
| import pytest | |
| from PIL import Image | |
| sys.path.insert(0, ".") | |
| from image_utils import ( | |
| _b64_to_pil, | |
| _pil_to_cv2, | |
| _cv2_to_pil, | |
| _crop_face_thumb, | |
| _pil_thumb_to_b64, | |
| _sort_faces_left_to_right, | |
| _face_to_dict, | |
| _collect_source_pils, | |
| ) | |
| # ββ Shared fixtures ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ | |
| def small_rgb_pil(): | |
| return Image.new("RGB", (4, 4), color=(255, 0, 0)) | |
| def small_rgb_b64(small_rgb_pil): | |
| buf = BytesIO() | |
| small_rgb_pil.save(buf, format="JPEG") | |
| raw = base64.b64encode(buf.getvalue()).decode() | |
| return f"data:image/jpeg;base64,{raw}" | |
| def small_cv2_bgr(): | |
| return np.zeros((4, 4, 3), dtype=np.uint8) | |
| def large_rgb_pil(): | |
| return Image.new("RGB", (200, 200), color=(255, 0, 0)) | |
| def fake_face(): | |
| face = MagicMock() | |
| face.bbox = [40.0, 40.0, 120.0, 120.0] | |
| face.det_score = 0.987654 | |
| return face | |
| # ββ _b64_to_pil βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ | |
| class TestB64ToPil: | |
| def test_with_data_header(self, small_rgb_b64): | |
| pil = _b64_to_pil(small_rgb_b64) | |
| assert isinstance(pil, Image.Image) | |
| assert pil.mode == "RGB" | |
| def test_without_data_header(self, small_rgb_pil): | |
| buf = BytesIO() | |
| small_rgb_pil.save(buf, format="JPEG") | |
| raw = base64.b64encode(buf.getvalue()).decode() | |
| pil = _b64_to_pil(raw) | |
| assert isinstance(pil, Image.Image) | |
| def test_invalid_raises(self): | |
| with pytest.raises(Exception): | |
| _b64_to_pil("data:image/jpeg;base64,not_valid_base64!!") | |
| # ββ _pil_to_cv2 βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ | |
| class TestPilToCv2: | |
| def test_returns_numpy_array(self, small_rgb_pil): | |
| arr = _pil_to_cv2(small_rgb_pil) | |
| assert isinstance(arr, np.ndarray) | |
| def test_shape_preserved(self, small_rgb_pil): | |
| arr = _pil_to_cv2(small_rgb_pil) | |
| assert arr.shape == (small_rgb_pil.height, small_rgb_pil.width, 3) | |
| def test_channel_order_is_bgr(self, small_rgb_pil): | |
| arr = _pil_to_cv2(small_rgb_pil) | |
| assert arr[0, 0, 2] == 255 # R in BGR | |
| assert arr[0, 0, 0] == 0 # B in BGR | |
| # ββ _cv2_to_pil βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ | |
| class TestCv2ToPil: | |
| def test_returns_pil_image(self, small_cv2_bgr): | |
| assert isinstance(_cv2_to_pil(small_cv2_bgr), Image.Image) | |
| def test_mode_is_rgb(self, small_cv2_bgr): | |
| assert _cv2_to_pil(small_cv2_bgr).mode == "RGB" | |
| def test_roundtrip(self, small_rgb_pil): | |
| back = _cv2_to_pil(_pil_to_cv2(small_rgb_pil)) | |
| assert back.size == small_rgb_pil.size | |
| # ββ _crop_face_thumb ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ | |
| class TestCropFaceThumb: | |
| def test_output_is_given_size(self, small_rgb_pil): | |
| assert _crop_face_thumb(small_rgb_pil, [1, 1, 3, 3], size=64).size == (64, 64) | |
| def test_bbox_near_edge_clamped(self): | |
| img = Image.new("RGB", (20, 20), color=(128, 128, 128)) | |
| assert _crop_face_thumb(img, [0, 0, 5, 5], size=32).size == (32, 32) | |
| def test_bbox_near_right_edge_clamped(self): | |
| img = Image.new("RGB", (20, 20)) | |
| assert _crop_face_thumb(img, [15, 15, 20, 20], size=32).size == (32, 32) | |
| # ββ _pil_thumb_to_b64 βββββββββββββββββββββββββββββββββββββββββββββββββββββββββ | |
| class TestPilThumbToB64: | |
| def test_has_data_header(self, small_rgb_pil): | |
| assert _pil_thumb_to_b64(small_rgb_pil).startswith("data:image/jpeg;base64,") | |
| def test_is_decodable_base64(self, small_rgb_pil): | |
| _, encoded = _pil_thumb_to_b64(small_rgb_pil).split(",", 1) | |
| assert base64.b64decode(encoded)[:2] == b"\xff\xd8" # JPEG magic bytes | |
| # ββ _sort_faces_left_to_right βββββββββββββββββββββββββββββββββββββββββββββββββ | |
| class TestSortFaces: | |
| def _make_face(self, x1): | |
| f = MagicMock() | |
| f.bbox = [float(x1), 0.0, float(x1 + 10), 10.0] | |
| return f | |
| def test_sorted_ascending(self): | |
| faces = [self._make_face(50), self._make_face(10), self._make_face(30)] | |
| result = _sort_faces_left_to_right(faces) | |
| assert [f.bbox[0] for f in result] == sorted(f.bbox[0] for f in faces) | |
| def test_empty_list(self): | |
| assert _sort_faces_left_to_right([]) == [] | |
| def test_single_face(self): | |
| face = self._make_face(5) | |
| assert _sort_faces_left_to_right([face]) == [face] | |
| # ββ _face_to_dict βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ | |
| class TestFaceToDict: | |
| def test_has_required_keys(self, large_rgb_pil, fake_face): | |
| assert {"idx", "thumbnail", "bbox", "det_score"} <= _face_to_dict( | |
| 0, fake_face, large_rgb_pil | |
| ).keys() | |
| def test_idx_matches(self, large_rgb_pil, fake_face): | |
| assert _face_to_dict(3, fake_face, large_rgb_pil)["idx"] == 3 | |
| def test_bbox_is_list_of_ints(self, large_rgb_pil, fake_face): | |
| bbox = _face_to_dict(0, fake_face, large_rgb_pil)["bbox"] | |
| assert isinstance(bbox, list) | |
| assert all(isinstance(v, int) for v in bbox) | |
| def test_det_score_rounded_to_3dp(self, large_rgb_pil, fake_face): | |
| assert _face_to_dict(0, fake_face, large_rgb_pil)["det_score"] == round( | |
| fake_face.det_score, 3 | |
| ) | |
| def test_thumbnail_has_header(self, large_rgb_pil, fake_face): | |
| assert _face_to_dict(0, fake_face, large_rgb_pil)["thumbnail"].startswith( | |
| "data:image/jpeg;base64," | |
| ) | |
| # ββ _collect_source_pils ββββββββββββββββββββββββββββββββββββββββββββββββββββββ | |
| class TestCollectSourcePils: | |
| def test_returns_pil_list(self, small_rgb_b64): | |
| result = _collect_source_pils([0, 1], {"0": small_rgb_b64, "1": small_rgb_b64}) | |
| assert len(result) == 2 | |
| assert all(isinstance(p, Image.Image) for p in result) | |
| def test_skips_missing_indices(self, small_rgb_b64): | |
| result = _collect_source_pils([0, 1], {"0": small_rgb_b64}) | |
| assert len(result) == 1 | |