110 lines
3.0 KiB
Python
Executable File
110 lines
3.0 KiB
Python
Executable File
#!/usr/bin/env python3
|
|
"""
|
|
人脸裁剪处理脚本
|
|
从单张图像中检测人脸,裁剪并调整大小到指定尺寸
|
|
"""
|
|
import os
|
|
from PIL import Image
|
|
import numpy as np
|
|
|
|
from .cpu_face_handler import CPUFaceHandler
|
|
|
|
def get_scaled_bbox(
|
|
bbox, img_w, img_h, ratio: float = 1.0, face_image: Image.Image = None
|
|
):
|
|
"""
|
|
根据人脸边界框计算缩放后的裁剪区域
|
|
|
|
Args:
|
|
bbox: 人脸边界框 [x1, y1, x2, y2]
|
|
img_w: 图像宽度
|
|
img_h: 图像高度
|
|
ratio: 缩放比例,数值越大,人脸在画面中的比例越小(周围留白越多)
|
|
face_image: PIL Image 对象
|
|
|
|
Returns:
|
|
裁剪后的人脸图像
|
|
"""
|
|
x1, y1, x2, y2 = bbox
|
|
|
|
# Calculate center point
|
|
center_x = (x1 + x2) / 2
|
|
center_y = (y1 + y2) / 2
|
|
|
|
# Calculate width and height
|
|
width = x2 - x1
|
|
|
|
# Scale width and height
|
|
new_width = width * ratio
|
|
new_height = new_width
|
|
|
|
# tile pix
|
|
dis_x_left = new_width * 0.5
|
|
dis_x_right = new_width - dis_x_left # 0.5new_width
|
|
dis_y_up = new_height * 0.55
|
|
dis_y_down = new_height - dis_y_up # 0.45new_height
|
|
|
|
# Calculate new coordinates
|
|
new_x1 = int(max(0, center_x - dis_x_left))
|
|
new_y1 = int(max(0, center_y - dis_y_up))
|
|
new_x2 = int(min(img_w, center_x + dis_x_right))
|
|
new_y2 = int(min(img_h, center_y + dis_y_down))
|
|
scaled_bbox = [new_x1, new_y1, new_x2, new_y2]
|
|
crop_face = face_image.crop(scaled_bbox)
|
|
return crop_face
|
|
|
|
|
|
def process_image(
|
|
input_path,
|
|
face_ratio=2.0,
|
|
target_size=(512, 512),
|
|
):
|
|
"""
|
|
处理单张图像,进行人脸检测和裁剪
|
|
|
|
Args:
|
|
input_path: 输入图像路径
|
|
face_ratio: 人脸缩放比例,建议范围:1.5-3.0,默认2.0
|
|
target_size: 输出图像尺寸,默认(512, 512)
|
|
|
|
Returns:
|
|
imgae: 处理后的图像
|
|
"""
|
|
# 初始化人脸检测器
|
|
face_detector = CPUFaceHandler()
|
|
|
|
# 验证输入文件
|
|
if not os.path.isfile(input_path):
|
|
raise ValueError(f"File not found: {input_path}")
|
|
|
|
try:
|
|
# 读取图像
|
|
image = Image.open(input_path)
|
|
image = image.convert("RGB")
|
|
image_rgb = np.array(image)
|
|
img_h, img_w = image_rgb.shape[:2]
|
|
|
|
# 检测人脸
|
|
boxes, scores = face_detector(image_rgb)
|
|
|
|
if len(boxes) == 0:
|
|
raise ValueError("No face detected")
|
|
|
|
# 转换边界框坐标(从相对坐标转为绝对坐标)
|
|
boxes_abs = [
|
|
boxes[0][0] * img_w,
|
|
boxes[0][1] * img_h,
|
|
boxes[0][2] * img_w,
|
|
boxes[0][3] * img_h
|
|
]
|
|
|
|
# 裁剪人脸
|
|
crop_face = get_scaled_bbox(boxes_abs, img_w, img_h, face_ratio, image)
|
|
|
|
# 调整大小
|
|
crop_face = crop_face.resize(target_size)
|
|
|
|
return crop_face
|
|
|
|
except Exception as e:
|
|
raise ValueError(f"Error processing {input_path}: {e}") |