Thiago Hersan
try new factor for scaling face
6d91907
import cv2
import gradio as gr
import numpy as np
from huggingface_hub import hf_hub_download
from math import atan2
from PIL import Image as PImage
from ultralytics import YOLO
OUT_W = 130
OUT_H = 170
OUT_EYE_SPACE = 64
OUT_FACE_WIDTH = 89
OUT_NOSE_TOP = 72
EYE_0_IDX = 36
EYE_1_IDX = 45
TEMPLE_0_IDX = 0
TEMPLE_1_IDX = 16
yolo_model_path = hf_hub_download(repo_id="AdamCodd/YOLOv11n-face-detection", filename="model.pt")
face_detector = YOLO(yolo_model_path)
LBFmodel = "./models/lbfmodel.yaml"
landmark_detector = cv2.face.createFacemarkLBF()
landmark_detector.loadModel(LBFmodel)
NUM_OUTS = 16
all_outputs = [gr.Image(format="jpeg", visible=False) for _ in range(NUM_OUTS)]
def face(img_in):
out_pad = NUM_OUTS * [gr.Image(visible=False)]
if img_in is None:
return out_pad
img = img_in.copy()
img.thumbnail((1000,1000))
img_np = np.array(img).copy()
iw,ih = img.size
output = face_detector.predict(img, verbose=False)
if len(output) < 1 or len(output[0]) < 1:
return out_pad
faces_xyxy = output[0].boxes.xyxy.numpy()
faces = np.array([[x0, y0, (x1 - x0), (y1 - y0)] for x0,y0,x1,y1 in faces_xyxy])
biggest_faces = faces[np.argsort(-faces[:,2])]
_, landmarks = landmark_detector.fit(img_np, biggest_faces)
if len(landmarks) < 1:
return out_pad
out_images = []
for landmark in landmarks:
eye0 = np.array(landmark[0][EYE_0_IDX])
eye1 = np.array(landmark[0][EYE_1_IDX])
temple0 = np.array(landmark[0][TEMPLE_0_IDX])
temple1 = np.array(landmark[0][TEMPLE_1_IDX])
mid = np.mean([eye0, eye1], axis=0)
eye_line = eye1 - eye0
tilt = atan2(eye_line[1], eye_line[0])
tilt_deg = 180 * tilt / np.pi
scale = min(OUT_EYE_SPACE / np.linalg.norm(eye1 - eye0),
OUT_FACE_WIDTH / np.linalg.norm(temple1 - temple0))
img_s = img.resize((int(iw * scale), int(ih * scale)))
# rotate around nose
new_mid = [int(c * scale) for c in mid]
crop_box = (new_mid[0] - (OUT_W // 2),
new_mid[1] - OUT_NOSE_TOP,
new_mid[0] + (OUT_W // 2),
new_mid[1] + (OUT_H - OUT_NOSE_TOP))
img_out = img_s.rotate(tilt_deg, center=new_mid, resample=PImage.Resampling.BICUBIC).crop(crop_box).convert("L")
out_images.append(gr.Image(img_out, visible=True))
out_images += out_pad
return out_images[:NUM_OUTS]
with gr.Blocks() as demo:
gr.Markdown("""
# 5020A Face Alignment Tool.
## Interface for face detection, alignment, cropping\
to help create dataset for [WK11](https://github.com/PSAM-5020-2025S-A/WK11) / [HW11](https://github.com/PSAM-5020-2025S-A/Homework11).
""")
gr.Interface(
face,
inputs=gr.Image(type="pil"),
outputs=all_outputs,
cache_examples=True,
examples=[["./imgs/03.webp"], ["./imgs/11.jpg"], ["./imgs/people.jpg"]],
allow_flagging="never",
)
if __name__ == "__main__":
demo.launch()