Selectable-Face-Swap / image_utils.py
someone-in-the-world's picture
Claude Sonnet 4.6
Auto-detect and crop source face on upload
6c691e6
Raw History Blame Contribute Delete
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