zoukankan      html  css  js  c++  java
  • 视频抽帧那点事

    视频抽帧

    视频文件是多媒体数据中比较常见的一种,也是入门门槛比较高的一个领域。视频数据相关的领域任务包括视频物体检测、视频物体追踪、视频分类、视频检索和视频摘要抽取等。

    视频数据与图像数据非常类似,都是由像素点组成的数据。在视频数据在非音频部分基本上可以视为多帧(张)图像数据的拼接,即三维图像的组合。由于视频数据与图像数据的相似性,在上述列举的视频领域任务中大都可以借助图像方法来完成。

    文本将讲解视频抽帧的几种方法,具体包括以下几种抽帧方式:

    • 抽取视频关键帧(IPB帧)
    • 抽取视频场景转换帧
    • 按照时间进行均匀抽帧
    • 抽取制定时间的视频帧

    在进行讲解具体的抽帧方式之前,我不得不介绍下FFmpeg。FFmpeg是一套可以用来编码、解码、合成和转换音频和视频数据的开源软件,提供了非常全面的音视频处理功能。如果你的工作内容是视频相关,那么ffmpeg是必须要掌握的软件了。FFmpeg提供了常见音视频和编解码方式,能够对众多的音视频格式进行读取,基本上所有的软件都会借助FFmpeg来完成音视频的读取操作。

    FFmpeg的学习资料可以参考:

    # 查看视频信息
    > ffmpeg -i 666051400.mp4
    Input #0, mov,mp4,m4a,3gp,3g2,mj2, from '666051400.mp4':
      Metadata:
        major_brand     : isom
        minor_version   : 512
        compatible_brands: isomiso2avc1mp41
        encoder         : Lavf57.56.100
      Duration: 00:17:02.00, start: 0.000000, bitrate: 374 kb/s
        Stream #0:0(und): Video: h264 (High) (avc1 / 0x31637661), yuv420p, 
        Metadata:
          handler_name    : VideoHandler
        Stream #0:1(und): Audio: aac (LC) (mp4a / 0x6134706D), 44100 Hz
        Metadata:
          handler_name    : SoundHandler
    At least one output file must be specified

    抽取视频关键帧(IPB帧)

    视频关键帧(Video Keyframes)是用于视频压缩和视频编解码的帧,视频关键帧是包含了完整信息的帧,其他的非关键帧将会使用与关键帧的差值进行压缩。视频帧具体可以分为IPB帧三种:

    • I帧表示关键帧,是最完整的帧画面,一般视频封面都选择I帧;
    • P帧单预测帧,利用之前的I帧或P帧,采用运动预测的方式进行帧间预测编码;
    • B帧双向预测帧,利用双向帧进行预测编码;

    一般情况下关键帧`I帧`是信息最多的帧,也是用途最多的帧。在视频检索和视频分类任务中一般都借助`I帧`来完成,在一个时长60s的视频中,可以抽取得到16个I帧、84个P帧和184个B,I帧数量少包含的信息却是最多的。

    • 使用ffprobe提取出IPB帧的时间:
    ffprobe -i 666051400.mp4 -v quiet -select_streams v -show_entries frame=pkt_pts_time,pict_type
    • 抽取IPB帧到jpg图片:
    # 抽取I帧
    ffmpeg -i 666051400.mp4 -vf "select=eq(pict_type\,I)"  -vsync vfr -qscale:v 2 -f image2 ./%08d.jpg
    
    # 抽取P帧
    ffmpeg -i 666051400.mp4 -vf "select=eq(pict_type\,P)"  -vsync vfr -qscale:v 2 -f image2 ./%08d.jpg
    
    # 抽取B帧
    ffmpeg -i 666051400.mp4 -vf "select=eq(pict_type\,B)"  -vsync vfr -qscale:v 2 -f image2 ./%08d.jpg

    由于ffmpeg抽取帧并无法按照时间戳来命名,需要手动将ffprobe提取出来的帧时间与抽取帧的图片进行对应重命名。关键帧具体的定义和用途可以参考:

    抽取视频场景转换帧

    在视频中可以按照视频的镜头切换可以将视频分为不同的场景(scene boundaries),为了直观感受可以观看下面一个视频。

    http://www.scikit-video.org/stable/_static/scene_cuts.mp4​www.scikit-video.org

    视频场景抽取算法一般是使用帧间的相似差异程度来衡量,如果视频帧大于某一个阈值则认为是一个新的场景,否则不是一个新的场景。在scikit-video中提供了颜色相似度和边缘相似度两种度量方式,思路非常简单:

    但是在我自己试验的过程中发现scikit-video中的场景检测非常慢,一个视频需要几分钟才能计算得到结果。后来在阅读ffmpeg文档过程中发现,ffmpeg早就有场景检测的命令,而且速度飞快。

    # https://ffmpeg.org/ffmpeg-filters.html#select_002c-aselect
    # 其中0.1表示帧为新场景的概率
    ffmpeg -i 666051400.mp4 -filter:v "select='gt(scene,0.1)',showinfo" -f null - 2>&1

    scikit-video的场景检测速度慢是以下原因:scikit-video中场景检测的实现方式是读取所有的视频帧,这个步骤非常耗时;而ffmpeg能够根据视频帧的压缩情况来选择性读取帧,速度就非常快了。但是scikit-video库还是很直观的,我也从库源代码学习到了很多。

    如果ffmpeg有对应的功能命令,优先使用ffmpeg来完成。

    均匀抽帧

    # -r 指定抽取的帧率,即从视频中每秒钟抽取图片的数量。1代表每秒抽取一帧。
    ffmpeg -i 666051400.mp4 -r 1 -q:v 2 -f image2 ./%08d.000000.jpg

    抽取制定时间的帧

    # 耗时0.07s
    ffmpeg -ss 00:00:30 -i 666051400.mp4 -vframes 1 0.jpg
    
    # 耗时0.68s
    ffmpeg -i 666051400.mp4 -ss 00:00:30  -vframes 1 0.jpg

    为什么上述两个命令时间差距这么大呢,也就是-i与-ss的位置换了一下。区别就是如果-ss在前面,则会使用关键帧信息来进行索引,则会非常快。

    文章来自:https://zhuanlan.zhihu.com/p/85895180?utm_source=wechat_session&utm_medium=social&utm_oi=46204255731712

  • 相关阅读:
    centos 6.5 添加静态ip
    质数因子
    sizeof 和 strlen 的区别
    C++输入带空格的字符串
    字符集合
    汽水瓶
    算法汇总
    Word目录生成
    0-1背包问题的动态规划法与回溯法
    vue父元素调用子组件的方法报undefined
  • 原文地址:https://www.cnblogs.com/LLBFWH/p/11660530.html
Copyright © 2011-2022 走看看