人像视频预处理【时间裁剪+画面裁切+调整帧率】

在视频处理中,cut(裁剪)、crop(画面裁切)和fps(帧率调整)这三个操作的顺序安排对最终的视频质量和效率有重要影响。以下是一种推荐的顺序和理由,旨在提高效率和减少错误:

1. **Cut(裁剪)**
- 首先进行时间裁剪(cut),去除不需要的视频片段,比如开头和结尾的无用部分或是中间的冗余场景。这样做的好处是在后续处理中减少了需要处理的视频数据量,节省了计算资源和时间。

2. **Crop(画面裁切)**
- 接下来进行画面裁切(crop)。裁切视频画面可以集中在视频中的关键区域,如之前提到的以主要人物为中心的画面裁切。在裁切之后,视频的分辨率会降低,这可能会影响后续的帧率调整过程中的编码速度和质量。但是,由于在裁切后视频的数据量已经减少,因此在帧率调整时处理速度会更快。

3. **Adjust FPS(调整帧率)**
- 最后调整帧率(fps)。调整帧率通常涉及丢弃或重复某些帧以达到目标帧率,这在裁切之后进行可以减少不必要的计算。如果在裁切前调整帧率,你可能会在裁切阶段失去一些不必要的帧,这可能会稍微影响视频的质量,尤其是当目标帧率低于原帧率时。此外,帧率调整通常涉及到重新编码,而较低分辨率的视频重新编码的速度通常比高分辨率的视频快。

综上所述,按照**裁剪** → **画面裁切** → **调整帧率**的顺序执行,可以最大化效率和资源利用,同时保持较好的视频质量。此外,这种顺序也有助于减少潜在的错误,因为每一步都在前一步的基础上进行,减少了数据的冗余处理。

然而,具体步骤还取决于你的视频编辑软件或库的功能和优化情况。在某些情况下,如果软件在特定顺序下提供了更高效的处理方式,那么遵循该软件的最佳实践也是明智的选择。例如,在使用某些视频处理库时,它们可能已经优化了某些操作的顺序,以提供更好的性能或避免常见的陷阱。

完整代码

#  python data_utils/pre_video/cut_crop_fps.py
import cv2
import numpy as np
import face_recognition
from moviepy.editor import VideoFileClip, concatenate_videoclips
from tqdm import tqdm

def find_host_face_location(video_path):
    """ 在视频的前几秒内检测并返回主持人面部的大致位置 """
    cap = cv2.VideoCapture(video_path)
    found_face = False
    host_face_location = None
    
    while cap.isOpened():
        ret, frame = cap.read()
        if not ret:
            break
        
        # 缩小帧尺寸以加快处理速度
        small_frame = cv2.resize(frame, (0, 0), fx=0.25, fy=0.25)
        rgb_small_frame = small_frame[:, :, ::-1]
        
        # 检测人脸
        face_locations = face_recognition.face_locations(rgb_small_frame)
        
        if face_locations:
            # 取第一张脸的位置,假设主持人位于视频画面的中心位置附近
            host_face_location = face_locations[0]
            # 将位置放大回原始大小
            host_face_location = (host_face_location[0]*4, host_face_location[1]*4, host_face_location[2]*4, host_face_location[3]*4)
            found_face = True
            break
    
    cap.release()
    return host_face_location if found_face else None

def calculate_cropping_box(face_location, frame_shape):
    """ 根据主持人面部位置计算裁剪框 """
    top, right, bottom, left = face_location
    center_x, center_y = (left + right) // 2, (top + bottom) // 2
    half_width, half_height = 256, 256
    
    left_cropped = max(center_x - half_width, 0)
    top_cropped = max(center_y - half_height, 0)
    right_cropped = min(center_x + half_width, frame_shape[1])
    bottom_cropped = min(center_y + half_height, frame_shape[0])
    
    return (top_cropped, right_cropped, bottom_cropped, left_cropped)

def find_first_last_face(video_path):
    """ 找到视频中第一次和最后一次出现人脸的时间戳 """
    cap = cv2.VideoCapture(video_path)
    first_face_time = None
    last_face_time = 0
    
    while cap.isOpened():
        ret, frame = cap.read()
        if not ret:
            break
        
        timestamp = cap.get(cv2.CAP_PROP_POS_MSEC) / 1000  # Convert to seconds
        if not first_face_time:
            # 缩小帧尺寸以加快处理速度
            small_frame = cv2.resize(frame, (0, 0), fx=0.25, fy=0.25)
            rgb_small_frame = small_frame[:, :, ::-1]
            
            # 检测人脸
            face_locations = face_recognition.face_locations(rgb_small_frame)
            
            if face_locations:
                first_face_time = timestamp
        
        if face_locations:
            last_face_time = timestamp
    
    cap.release()
    return first_face_time, last_face_time

def process_video(input_path, output_path):
    """ 处理视频,裁剪并调整帧率 """
    # 检测主持人面部位置
    host_face_location = find_host_face_location(input_path)
    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(input_path)
    
    # 裁剪视频以保留第一次和最后一次出现人脸的部分
    start_trim = max(0, first_face_time - 1)  # 增加1秒缓冲区
    end_trim = min(last_face_time + 1, clip.duration)  # 确保不会超出视频的总长度
    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()

if __name__ == "__main__":
    for i in tqdm(range(1, 76), desc="Processing videos"):
        input_path = f"data/dataset/{i}/{i}.mp4"
        output_path = f"data/dataset/{i}/{i}_fcc.mp4"
        process_video(input_path, output_path)

相关推荐

  1. 调整视频、分辨率

    2024-07-15 13:44:02       30 阅读
  2. 人脸检测+调整分辨率+调整

    2024-07-15 13:44:02       25 阅读
  3. ffmpeg裁剪视频画面

    2024-07-15 13:44:02       65 阅读
  4. 视频调整、分辨率+音画同步

    2024-07-15 13:44:02       29 阅读
  5. [python-opencv] PNG 物体

    2024-07-15 13:44:02       39 阅读
  6. 视频基础学习三——视频、码与分辨率

    2024-07-15 13:44:02       90 阅读

最近更新

  1. docker php8.1+nginx base 镜像 dockerfile 配置

    2024-07-15 13:44:02       67 阅读
  2. Could not load dynamic library ‘cudart64_100.dll‘

    2024-07-15 13:44:02       71 阅读
  3. 在Django里面运行非项目文件

    2024-07-15 13:44:02       58 阅读
  4. Python语言-面向对象

    2024-07-15 13:44:02       69 阅读

热门阅读

  1. 优化调试体验:让PyCharm的调试过程飞起来

    2024-07-15 13:44:02       24 阅读
  2. C 习题答案20240710-前置

    2024-07-15 13:44:02       23 阅读
  3. 使用css3实现【水波纹扩散效果】

    2024-07-15 13:44:02       25 阅读
  4. C++小白Python选手2小时入门C++

    2024-07-15 13:44:02       29 阅读
  5. 树莓派pico入坑笔记,at24c256使用

    2024-07-15 13:44:02       21 阅读
  6. Postcat使用全解析

    2024-07-15 13:44:02       24 阅读
  7. Mojo 编程语言入门:AI开发者的新宠儿

    2024-07-15 13:44:02       25 阅读
  8. 721. 账户合并

    2024-07-15 13:44:02       22 阅读
  9. ZZULIOJ1073: 再谈鸡兔同笼问题

    2024-07-15 13:44:02       21 阅读
  10. git统计工程某目录代码总行数

    2024-07-15 13:44:02       21 阅读