|
from retinaface import RetinaFace
|
|
from PIL import Image
|
|
import torch
|
|
|
|
|
|
|
|
def auto_crop_image(image_path=r"F:\V_Express_V1\Material\Biden_Photo_Big.png", expand_percent=0.15, crop_size=(512, 512)):
|
|
|
|
if torch.cuda.is_available():
|
|
device = 'cuda'
|
|
print("Using GPU for RetinaFace detection.")
|
|
else:
|
|
device = 'cpu'
|
|
print("Using CPU for RetinaFace detection.")
|
|
|
|
|
|
img = Image.open(image_path)
|
|
|
|
|
|
faces = RetinaFace.detect_faces(image_path)
|
|
|
|
if not faces:
|
|
print("No faces detected.")
|
|
return None
|
|
|
|
|
|
|
|
face = list(faces.values())[0]
|
|
landmarks = face['landmarks']
|
|
|
|
|
|
right_eye = landmarks['right_eye']
|
|
left_eye = landmarks['left_eye']
|
|
right_mouth = landmarks['mouth_right']
|
|
left_mouth = landmarks['mouth_left']
|
|
|
|
|
|
eye_distance = abs(right_eye[0] - left_eye[0])
|
|
|
|
|
|
head_width = eye_distance * 4.5
|
|
head_height = eye_distance * 6.5
|
|
|
|
|
|
eye_center_x = (right_eye[0] + left_eye[0]) // 2
|
|
eye_center_y = (right_eye[1] + left_eye[1]) // 2
|
|
|
|
|
|
head_left = max(0, int(eye_center_x - head_width // 2))
|
|
head_top = max(0, int(eye_center_y - head_height // 2))
|
|
head_right = min(img.width, int(eye_center_x + head_width // 2))
|
|
head_bottom = min(img.height, int(eye_center_y + head_height // 2))
|
|
|
|
|
|
assumed_head_img = img.crop((head_left, head_top, head_right, head_bottom))
|
|
assumed_head_img.save("assumed_head.png", format='PNG')
|
|
|
|
|
|
expanded_w = int(head_width * (1 + expand_percent))
|
|
expanded_h = int(head_height * (1 + expand_percent))
|
|
|
|
|
|
center_x, center_y = head_left + head_width // 2, head_top + head_height // 2
|
|
left = max(0, center_x - expanded_w // 2)
|
|
right = min(img.width, center_x + expanded_w // 2)
|
|
top = max(0, center_y - expanded_h // 2)
|
|
bottom = min(img.height, center_y + expanded_h // 2)
|
|
|
|
|
|
cropped_img = img.crop((left, top, right, bottom))
|
|
cropped_img.save("expanded_face.png", format='PNG')
|
|
|
|
|
|
cropped_width, cropped_height = cropped_img.size
|
|
aspect_ratio = cropped_width / cropped_height
|
|
|
|
|
|
target_width = crop_size[0]
|
|
target_height = crop_size[1]
|
|
|
|
|
|
if aspect_ratio > target_width / target_height:
|
|
|
|
new_width = int(cropped_height * target_width / target_height)
|
|
left_crop = (cropped_width - new_width) // 2
|
|
right_crop = left_crop + new_width
|
|
top_crop = 0
|
|
bottom_crop = cropped_height
|
|
else:
|
|
|
|
new_height = int(cropped_width * target_height / target_width)
|
|
top_crop = (cropped_height - new_height) // 2
|
|
bottom_crop = top_crop + new_height
|
|
left_crop = 0
|
|
right_crop = cropped_width
|
|
|
|
|
|
final_cropped_img = cropped_img.crop((left_crop, top_crop, right_crop, bottom_crop))
|
|
final_cropped_img.save("final_cropped_img.png", format='PNG')
|
|
|
|
|
|
resized_img = final_cropped_img.resize(crop_size, resample=Image.LANCZOS)
|
|
|
|
|
|
resized_img_path = image_path.rsplit('.', 1)[0] + '_cropped.png'
|
|
resized_img.save("resized_img.png", format='PNG')
|
|
|
|
auto_crop_image() |