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

在视频处理中,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 math
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)
    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()

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

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mfbz.cn/a/800420.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Qt 多窗体、复用窗口的使用

1.继承自QWidge的窗口的呈现,作为tabPage呈现,作为独立窗口呈现 2.继承自QMainWindow的窗口的呈现,作为abPage呈现,作为独立窗口呈现 1. 继承自QWidge的窗口的呈现 1.1 作为tabPage呈现 void MutiWindowExample::on_actWidgetI…

AI绘画入门实践|Midjourney 提示词的使用技巧

提示词长短 尽可能做到简洁明了。 提示词很短 MJ 出图的随机性更高,创造的内容更有想象力,更适合创意发散的图像生成。 a dog 提示词很长 MJ 出图会更加精准,但描述太过详细,有可能出现AI理解不到位的情况。 越到后面的提示词&…

风险评估:IIS的安全配置,IIS安全基线检查加固

「作者简介」:冬奥会网络安全中国代表队,CSDN Top100,就职奇安信多年,以实战工作为基础著作 《网络安全自学教程》,适合基础薄弱的同学系统化的学习网络安全,用最短的时间掌握最核心的技术。 这一章节我们需…

Java面试八股之Redis集群Cluster

Redis集群Cluster Redis Cluster是一种基于数据分片(Sharding)的分布式缓存和存储系统,它实现了数据的水平扩展、高可用性和自动故障转移。以下是对Redis Cluster模式详细实现流程的描述: 1. 初始化与配置 部署节点&#xff1a…

flutter 手写 TabBar

前言: 这几天在使用 flutter TabBar 的时候 我们的设计给我提了一个需求: 如下 Tabbar 第一个元素 左对齐,试了下TabBar 的配置,无法实现这个需求,他的 配置是针对所有元素的。而且 这个 TabBar 下面的 滑块在移动的时…

产品经理-产品经理会在项目中遇到的几个问题(16)

项目中遇到了需求变更怎么办? 首先要弄清楚需求变更的原因是什么。如果是因为在迭代的过程中更好地理解了用户需求 进而产生了更好的需求则完全是正常的。如果是因为老板的需求 那就需要和老板沟通清楚,并且确保自己能理解老板的需求,而且这个…

软件测试——测试用例

工作职责: 1.负责产品系统测试,包括功能测试、性能测试、稳定性测试、用户场景测试、可靠性测试等。 2.负责测试相关文档的编写,包括测试计划、测试用例、测试报告等。 3.负责自动化测试框架、用例的维护。 岗位要求: 1.熟练…

800块,我从淘宝上买AGV……

导语 大家好,我是社长,老K。专注分享智能制造和智能仓储物流等内容。 新书《智能物流系统构成与技术实践》人俱乐部 从淘宝上打算够购买一台AGV小车,上去一搜,嘿,你别说,还真有。便宜的才200块钱。 很兴奋把…

17-8 向量数据库之野望8 - 7 个主流向量数据库

​​​​​​ 在快速发展的人工智能 (AI)、机器学习 (ML) 和数据工程领域,对高效数据存储和检索系统的需求至关重要。矢量数据库已成为管理这些技术通常依赖的复杂高维数据的关键解决方案。在这里,我们探讨了每个 AI/ML/数据工程师都应该熟悉的七个矢量数据库,重点介绍了它们…

【Linux】01.Linux 的常见指令

1. ls 指令 语法:ls [选项] [目录名或文件名] 功能:对于目录,该命令列出该目录下的所有子目录与文件。对于文件,将列出文件名以及其他信息 常用选项: -a:列出当前目录下的所有文件,包含隐藏文件…

JavaSE学习笔记第三弹之异常抛出

今天我们继续来学习JavaSE相关的知识,希望与大家共同努力。 目录 异常 什么是异常 运行时异常 编译时异常 ​编辑 为什么需要异常处理机制 错误 异常的处理与抛出 异常处理 异常抛出 自定义异常 结语 异常 什么是异常 Java中异常是一种在程序运行时发…

Java二十三种设计模式-原型模式(5/23)

Java中的原型模式:深入解析与应用实践 引言 原型模式(Prototype Pattern)是一种创建型设计模式,它使用一个已有的对象作为原型,通过复制这个原型来创建新的实例。这种模式适用于对象的创建成本较高,或者对…

BL201分布式I/O耦合器连接Profinet网络

钡铼技术的BL201分布式I/O耦合器是一个用于Profinet网络的设备,用于连接远程输入/输出(I/O)设备到控制系统,如可编程逻辑控制器(PLC),能够实现分布式的I/O连接和通信。 它支持标准Profinet IO …

Qt实现一个简单的视频播放器

目录 1 工程配置 1.1 创建新工程 1.2 ui界面配置 1.3 .pro配置 2 代码 2.1 main.c代码 2.2 widget.c 2.3 widget.h 本文主要记述了如何使用Qt编写一个简单的视频播放器,整个示例采用Qt自带组件就可以完成。可以实现视频的播放和暂停等功能。 1 工程配置 1.…

都说油车不行了,外资两款经典油车降价起量,与电动车展开决战

6月份的轿车销量数据出来了,数据显示电动汽车并没稳赢,燃油车终于发力了,反过来围剿电动汽车了,显示出消费者并非说不买油车,而是看价格,价格合适,消费者仍然会选择油车。 6月份的数据显示之前销…

AV1 编码标准帧间预测技术概述

AV1 编码标准帧间预测 AV1(AOMedia Video1)是一种开源的视频编码格式,它在帧间预测技术上做出了显著的改进和扩展,以提供比现有标准更高的压缩效率和更好的视频质量。以下是AV1帧间预测技术的几个关键点: 参考帧扩展&a…

VGMP(VRRP组管理协议)和HRP(华为冗余技术)

1、VGMP VGMP(VRRP Group Management Protocol):VRRP组管理协议,是华为开发的一种私有协议,主要用于实现对多个VRRP组进行统一管理的功能 概述:VGMP协议是在VRRP协议的基础上开发的,其最主要的…

linux的学习(五):shell编程中的变量,运算符,条件判断

简介: shell编程的基本概念,定义变量,运算符,条件判断的基本使用 shell编程 把多个命令写到一个文件里,这个文件就是脚本,里面还有很多的流程控制 基本概念 脚本的后缀名是.sh 脚本的执行:…

Golang | Leetcode Golang题解之第235题二叉搜索树的最近公共祖先

题目&#xff1a; 题解&#xff1a; func lowestCommonAncestor(root, p, q *TreeNode) (ancestor *TreeNode) {ancestor rootfor {if p.Val < ancestor.Val && q.Val < ancestor.Val {ancestor ancestor.Left} else if p.Val > ancestor.Val && q…

【Docker】Docker 的数据管理与镜像创建

目录 一.数据管理 1.数据卷 2.数据卷容器 二.端口映射 三.容器互联 四.Docker 镜像的创建 1.基于现有镜像创建 1.1.首先启动一个镜像&#xff0c;基于镜像创建容器&#xff0c;更新容器内容 1.2.将修改后的容器提交为新的镜像&#xff0c;需要使用该容器的 ID 号创建新…