Spaces:
Running on Zero
Running on Zero
Download image_utils.py from maxmcd/Selectable-Face-Swap: direct link, hf CLI and curl.
- Browser
- Download file 2.12 kB
-
https://huggingface.co/spaces/maxmcd/Selectable-Face-Swap/resolve/main/image_utils.py
- Command line
-
hf download hf://spaces/maxmcd/Selectable-Face-Swap/image_utils.py
-
curl -L -o image_utils.py https://huggingface.co/spaces/maxmcd/Selectable-Face-Swap/resolve/main/image_utils.py
2.12 kB
| import base64 | |
| import cv2 | |
| import numpy as np | |
| from io import BytesIO | |
| from PIL import Image | |
| THUMBNAIL_SIZE = 160 | |
| def _b64_to_pil(base64_string): | |
| header, _, data = base64_string.partition(",") | |
| raw = base64.b64decode(data if data else base64_string) | |
| return Image.open(BytesIO(raw)).convert("RGB") | |
| def _pil_to_cv2(image): | |
| return cv2.cvtColor(np.array(image), cv2.COLOR_RGB2BGR) | |
| def _cv2_to_pil(bgr_image): | |
| return Image.fromarray(cv2.cvtColor(bgr_image, cv2.COLOR_BGR2RGB)) | |
| def _crop_face_thumbnail(image, bbox, size): | |
| left, top, right, bottom = (int(c) for c in bbox) | |
| padding = max(int(max(right - left, bottom - top) * 0.35), 10) | |
| padded_left = max(0, left - padding) | |
| padded_top = max(0, top - padding) | |
| padded_right = min(image.width, right + padding) | |
| padded_bottom = min(image.height, bottom + padding) | |
| return image.crop((padded_left, padded_top, padded_right, padded_bottom)).resize( | |
| (size, size), Image.LANCZOS | |
| ) | |
| def _thumbnail_to_base64(thumbnail): | |
| buffer = BytesIO() | |
| thumbnail.save(buffer, format="JPEG", quality=88) | |
| return f"data:image/jpeg;base64,{base64.b64encode(buffer.getvalue()).decode()}" | |
| def _sort_faces_left_to_right(faces): | |
| return sorted(faces, key=lambda face: float(face.bbox[0])) | |
| def _face_to_dict(face_index, face, image): | |
| thumbnail = _crop_face_thumbnail(image, face.bbox, THUMBNAIL_SIZE) | |
| return { | |
| "idx": face_index, | |
| "thumbnail": _thumbnail_to_base64(thumbnail), | |
| "bbox": [int(c) for c in face.bbox], | |
| "det_score": round(float(face.det_score), 3), | |
| } | |
| def _pil_to_b64(image): | |
| buffer = BytesIO() | |
| image.save(buffer, format="JPEG", quality=88) | |
| return f"data:image/jpeg;base64,{base64.b64encode(buffer.getvalue()).decode()}" | |
| def _collect_source_images(selected_indices, sources): | |
| source_images = [] | |
| for face_index in selected_indices: | |
| source = sources.get(str(face_index)) | |
| if source: | |
| try: | |
| source_images.append(_b64_to_pil(source)) | |
| except Exception: | |
| pass | |
| return source_images | |