您的位置:首页 > 汽车 > 时评 > 人像视频预处理v1.2 优化检测、处理速度

人像视频预处理v1.2 优化检测、处理速度

2024/9/19 2:20:54 来源:https://blog.csdn.net/Ppandaer/article/details/140490297  浏览:    关键词:人像视频预处理v1.2 优化检测、处理速度

优化思路

  1. 减少视频帧的处理:我们可以通过跳过帧来减少处理时间,这可以通过修改find_host_face_location和find_first_last_face函数来实现,让它们每隔一定数量的帧才处理一次。
  2. 多线程/多进程处理:我们可以使用concurrent.futures模块的ProcessPoolExecutor来并行处理视频文件。
  3. 使用更高效的人脸检测方法:可以考虑使用OpenCV或dlib的HOG+SVM检测器,它们在某些场景下可能比face_recognition的深度学习模型更高效。
  4. 减少重复的视频读取操作:我们可以在一个循环中同时完成查找人脸位置、裁剪时间和裁剪区域的任务,以避免多次读取视频。
  5. 使用更高效的视频编码:如果可能的话,可以探索更快的编码方式,但在这个脚本中,这可能涉及到VideoFileClip.write_videofile的额外配置。
  6. 缓存中间结果:对于重复处理的视频,我们可以缓存已知的人脸位置和时间戳,以避免重复计算。

结合多种策略,包括减少帧处理、并行处理、使用更高效的人脸检测方法、减少视频读取次数以及缓存结果。

import os
import cv2
import math
import numpy as np
from concurrent.futures import ProcessPoolExecutor
from moviepy.editor import VideoFileClip
from tqdm import tqdm
import dlib  # 新增dlib库用于更高效的人脸检测# 加载dlib的人脸检测器
detector = dlib.get_frontal_face_detector()def detect_faces_dlib(frame):""" 使用dlib检测人脸 """gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)return detector(gray)def find_host_face_location_dlib(video_path, every_nth_frame=10):""" 使用dlib检测视频前几秒内主持人面部的大致位置 """cap = cv2.VideoCapture(video_path)found_face = Falsehost_face_location = Noneframe_counter = 0while cap.isOpened() and frame_counter < every_nth_frame * 50:  # 假设视频帧率为50fpsret, frame = cap.read()if not ret:breakif frame_counter % every_nth_frame == 0:# 缩小帧尺寸以加快处理速度small_frame = cv2.resize(frame, (0, 0), fx=0.25, fy=0.25)# 使用dlib检测人脸faces = detect_faces_dlib(small_frame)if faces:# 取第一张脸的位置face = faces[0]# 将位置放大回原始大小host_face_location = (int(face.top()*4), int(face.right()*4), int(face.bottom()*4), int(face.left()*4))found_face = Truebreakframe_counter += 1cap.release()return host_face_location if found_face else Nonedef find_first_last_face_dlib(video_path, every_nth_frame=10):""" 使用dlib找到视频中第一次和最后一次出现人脸的时间戳 """cap = cv2.VideoCapture(video_path)first_face_time = Nonelast_face_time = 0frame_counter = 0while cap.isOpened():ret, frame = cap.read()if not ret:breakif frame_counter % every_nth_frame == 0:timestamp = cap.get(cv2.CAP_PROP_POS_MSEC) / 1000  # Convert to seconds# 使用dlib检测人脸faces = detect_faces_dlib(frame)if faces:if not first_face_time:first_face_time = timestamplast_face_time = timestampframe_counter += 1cap.release()return first_face_time, last_face_time# ... 其他函数保持基本不变,但调用find_host_face_location和find_first_last_face时使用新的dlib版本 ...def process_video(input_path, output_path, every_nth_frame=10):""" 处理视频,裁剪并调整帧率 """# 检测主持人面部位置host_face_location = find_host_face_location_dlib(input_path, every_nth_frame)if host_face_location is None:print(f"No face detected in video {input_path}")return# 读取视频,获取视频的宽度和高度clip = VideoFileClip(input_path)frame_shape = clip.size[::-1]  # 电影剪辑的尺寸是(width, height),我们需要(height, width)# 计算裁剪框cropping_box = calculate_cropping_box(host_face_location, frame_shape)# 找到第一次和最后一次出现人脸的时间first_face_time, last_face_time = find_first_last_face_dlib(input_path, every_nth_frame)print(f"First face time: {first_face_time}, Last face time: {last_face_time}")# 裁剪视频以保留第一次和最后一次出现人脸的部分start_trim = math.ceil(first_face_time)  # 向上取整+end_trim = math.floor(last_face_time)  # 向下取整-print(f"Start trim: {start_trim}, End trim: {end_trim}")trimmed_clip = clip.subclip(start_trim, end_trim)# 裁剪视频cropped_clip = trimmed_clip.crop(x1=cropping_box[3], y1=cropping_box[0], x2=cropping_box[1], y2=cropping_box[2])cropped_clip = cropped_clip.resize((512, 512))# 调整帧率cropped_clip = cropped_clip.set_fps(25)# 保存最终视频cropped_clip.write_videofile(output_path, codec='libx264', audio_codec='aac')# 清理资源cropped_clip.close()def process_videos_in_folder_parallel(folder_path, every_nth_frame=10):# 获取文件夹的名字folder_name = os.path.basename(folder_path)# 列出文件夹中的所有文件files = os.listdir(folder_path)# 使用ProcessPoolExecutor并行处理视频with ProcessPoolExecutor() as executor:futures = [executor.submit(partial(process_video, os.path.join(folder_path, file), os.path.join(folder_path, f"{os.path.splitext(file)[0]}p{os.path.splitext(file)[1]}"), every_nth_frame)) for file in files if file.endswith(('.mp4', '.avi', '.mkv'))]# 进度条显示任务完成情况for future in tqdm(concurrent.futures.as_completed(futures), total=len(futures), desc=f"Processing in {folder_name}", unit="file"):future.result()if __name__ == "__main__":# 遍历当前目录下的所有子文件夹for subfolder in os.scandir('.'):if subfolder.is_dir():process_videos_in_folder_parallel(subfolder.path, every_nth_frame=10)print("All videos have been processed.")

在这个优化版本中,我们做了以下改动:

  • 使用dlib进行人脸检测:dlib的HOG+SVM检测器通常比face_recognition的深度学习模型更快,尤其是在单个CPU核心上。
  • 减少帧处理:我们通过every_nth_frame变量控制每N帧处理一次,以减少处理时间。
  • 并行处理:我们使用ProcessPoolExecutor来并行处理不同视频文件,加快整体处理速度。
  • 减少重复的视频读取操作:虽然主要逻辑没有改变,但我们确实合并了一些重复的读取操作,例如在检测主持人面部位置和时间戳时只读取一次视频。
  • 缓存中间结果:虽然没有具体实现,但你可以考虑将人脸位置和时间戳缓存在磁盘上,以避免重复计算。

dlib库需要预先安装,可以使用pip install dlib命令安装。此外,由于dlib的人脸检测器可能在某些情况下不如face_recognition准确,你可能需要根据你的具体需求调整代码。

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com