在做数字人时,需要对采集的数据进行预处理,然后才能进行模型训练, 预处理常用的操作有:去背景 音频重采样 视频裁剪 音频特征提取等等,今天我们来分享一个自动化脚本: 对原图/视频进行人脸检测并根据目标尺寸以人脸为中心进行裁剪.
目录
1. 效果
2. 对图片进行裁剪
3.对视频进行裁剪
一. 效果
1.1 对图片处理
1.2 对视频处理
比如最近做的下面这个数字人效果,在训练阶段就用到了该脚本对视频进行自动裁剪
训练微调后的数字人
二. 对图片进行裁剪
图片的处理比较简单: 读取图片,进行人脸检测,根据un人脸中心点坐标和目标尺寸对原图进行裁剪
def get_face_coordinates(image):
#cv读取的图片转为RGB格式,然后使用dlib进行人脸检测
rgb_image = cv2.cvtColor(image, cv2.COLOR_BGR2RGB)
detections = dlib.get_frontal_face_detector(rgb_image)
face = detections[0]
#计算并返回人脸中心点
center_x = (face.left() + face.right()) // 2
center_y = (face.top() + face.bottom()) // 2
return center_x, center_y
#读取图片
frame = cv2.imread(inputFile)
#进行人脸关键点检测,返回人脸中心点坐标
face_coords = get_face_coordinates(frame)
center_x, center_y = face_coords
#根据目标尺寸,计算出以人脸为中心点进行裁剪的起止坐标
crop_size = targetWH//2
start_x = max(center_x - crop_size, 0)
start_y = max(center_y - crop_size, 0)
#把裁剪的关键点坐标信息记录,由于后期融合处理
crop_coordinates = {
"start_x": start_x,
"start_y": start_y,
"width": targetWH,
"height": targetWH
}
crop_coordinates_path = outputFamesFolder + '/crop_coordinates.json'
with open(crop_coordinates_path, 'w') as file:
json.dump(crop_coordinates, file, indent=4)
#对原图进行裁剪
cropped_image = frame[start_y:start_y + targetWH, start_x:start_x + targetWH]
frame_filename = f"{outputFamesFolder}/frame_crop.png"
#保存裁剪后的图片
cv2.imwrite(frame_filename, cropped_image)
三. 对视频进行裁剪
如果是视频,想比较图片稍微复杂一些,
首先要分离音频和视频,
可以根据需要对音频按照目标采样率进行重采样
获取视频的第一帧,进行人脸关键点检测,作为后续所有帧的人脸坐标(所以采集的视频人脸进来不要动作太大)
逐帧读取视频裁剪 获取裁剪后的帧
对把裁剪后的帧和音频重新生成视频作为后续流程的输入
#读取视频
video_capture = cv2.VideoCapture(inputFile)
#获取第一帧的人脸坐标
ret, first_frame = video_capture.read()
face_coords = get_face_coordinates(first_frame)
center_x, center_y = face_coords
crop_size = targetWH//2
start_x = max(center_x - crop_size, 0)
start_y = max(center_y - crop_size, 0)
#根据第一帧的人脸坐标信息,逐帧进行裁剪
frame_number = 0
while video_capture.isOpened():
ret, frame = video_capture.read()
if not ret:
break
cropped_image = frame[start_y:start_y + targetWH, start_x:start_x + targetWH]
frame_filename = f"{outputFamesFolder}/frame_{frame_number:04d}.png"
cv2.imwrite(frame_filename, cropped_image)
frame_number += 1
video_capture.release()
#最终裁剪后的视频path
output_video_path = outputFolder + f"/{name}_face_crop.mp4"
# 提取视频的音频
cmd = [
"ffmpeg",
"-i",inputFile,
'-f','wav',
'-ar','16000',
'-y',audio_output
]
out = subprocess.run(cmd,\
stdout=subprocess.PIPE,\
stderr=subprocess.STDOUT,\
text=True)
#把裁剪人脸后的视频帧和音频无损合并为 最终的视频
cmd =[
"ffmpeg",
"-i",frame_pattern,
"-i",audio_output,
"-c:v","libx264",
"-framerate", str(targetFps),
"-c:a","copy",
"-crf","0",
"-preset","veryslow",
"-pix_fmt", "yuv420p",
"-movflags","faststart",
"-shortest",
"-y",output_video_path
]
out = subprocess.run(cmd,\
stdout=subprocess.PIPE,\
stderr=subprocess.STDOUT,\
text=True)
感谢你的阅读
接下来我们继续学习输出AIGC相关内容,关注公众号"音视频开发之旅",回复"人脸裁剪"获取封装后的完整代码,一起学习成长。
欢迎交流