下载地址:https://www.pan38.com/dow/share.php?code=JCnzE 提取密码:1121
代码实现了基于面部特征点的人脸动画生成,包括眨眼和张嘴动作。它使用dlib进行人脸检测和特征点定位,然后通过图像变形技术创建动画效果。请注意,这需要预先下载dlib的68点人脸特征点模型文件。
import cv2
import dlib
import numpy as np
from scipy.spatial import Delaunay
from skimage.transform import PiecewiseAffineTransform, warp
初始化dlib的人脸检测器和特征点预测器
detector = dlib.get_frontal_face_detector()
predictor = dlib.shape_predictor("shape_predictor_68_face_landmarks.dat")
def load_image(image_path):
img = cv2.imread(image_path)
if img is None:
raise ValueError(f"无法加载图像: {image_path}")
return cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
def get_landmarks(image):
gray = cv2.cvtColor(image, cv2.COLOR_RGB2GRAY)
rects = detector(gray, 1)
if len(rects) == 0:
raise ValueError("未检测到人脸")
shape = predictor(gray, rects[0])
return np.array([(shape.part(i).x, shape.part(i).y) for i in range(68)])
def create_blink_animation(image, landmarks, frames=10):
# 眼睛特征点索引(dlib 68点模型)
left_eye = landmarks[36:42]
right_eye = landmarks[42:48]
# 计算眼睛中心
left_eye_center = left_eye.mean(axis=0)
right_eye_center = right_eye.mean(axis=0)
# 创建动画帧
animation_frames = []
for i in range(frames):
# 计算当前帧的闭合程度 (0=完全睁开, 1=完全闭合)
if i < frames//2:
close_ratio = i / (frames//2)
else:
close_ratio = (frames - i) / (frames//2)
# 创建变形后的特征点
deformed_landmarks = landmarks.copy()
# 变形左眼
for j in range(36, 42):
original = landmarks[j]
direction = left_eye_center - original
deformed_landmarks[j] = original + direction * close_ratio * 0.7
# 变形右眼
for j in range(42, 48):
original = landmarks[j]
direction = right_eye_center - original
deformed_landmarks[j] = original + direction * close_ratio * 0.7
# 应用变形
warped_img = warp_image(image, landmarks, deformed_landmarks)
animation_frames.append(warped_img)
return animation_frames
def create_mouth_animation(image, landmarks, frames=10):
# 嘴巴特征点索引
mouth = landmarks[48:68]
mouth_center = mouth.mean(axis=0)
# 创建动画帧
animation_frames = []
for i in range(frames):
# 计算张嘴程度 (0=闭合, 1=完全张开)
if i < frames//2:
open_ratio = i / (frames//2)
else:
open_ratio = (frames - i) / (frames//2)
# 创建变形后的特征点
deformed_landmarks = landmarks.copy()
# 变形嘴巴
for j in range(48, 68):
original = landmarks[j]
if j in [48, 54]: # 嘴巴角落
direction = np.array([0, -1]) * 10 * open_ratio
else:
direction = mouth_center - original
direction = direction * 0.5 * open_ratio
deformed_landmarks[j] = original + direction
# 应用变形
warped_img = warp_image(image, landmarks, deformed_landmarks)
animation_frames.append(warped_img)
return animation_frames
def warp_image(image, src_points, dst_points):
# 创建三角剖分
tri = Delaunay(src_points)
# 创建PiecewiseAffineTransform对象
tform = PiecewiseAffineTransform()
tform.estimate(src_points[tri.simplices], dst_points[tri.simplices])
# 应用变形
warped = warp(image, tform, output_shape=image.shape[:2])
return (warped * 255).astype(np.uint8)
def save_animation(frames, output_path, fps=10):
height, width = frames[0].shape[:2]
fourcc = cv2.VideoWriter_fourcc(*'mp4v')
out = cv2.VideoWriter(output_path, fourcc, fps, (width, height))
for frame in frames:
out.write(cv2.cvtColor(frame, cv2.COLOR_RGB2BGR))
out.release()
def main():
# 加载图像
image_path = "input_face.jpg"
image = load_image(image_path)
# 获取特征点
landmarks = get_landmarks(image)
# 创建眨眼动画
blink_frames = create_blink_animation(image, landmarks)
# 创建张嘴动画
mouth_frames = create_mouth_animation(image, landmarks)
# 合并动画
combined_frames = blink_frames + mouth_frames
# 保存结果
save_animation(combined_frames, "output_animation.mp4")
print("动画生成完成!")
if name == "main":
main()