精华内容
下载资源
问答
  • 本发明属于信息安全技术领域,涉及视频内容信息的提取,具体来说,是一种视频关键帧提取算法。背景技术:随着Internet的应用和普及,多媒体信息检索系统对社会各领域产生越来越大的影响。传统的信息检索采用基于文本...

    2115448225542.gif

    本发明属于信息安全技术领域,涉及视频内容信息的提取,具体来说,是一种视频关键帧提取算法。

    背景技术:

    随着Internet的应用和普及,多媒体信息检索系统对社会各领域产生越来越大的影响。传统的信息检索采用基于文本的检索方式,查询时需要说明文本特征,要求用户对文本特征的描述具有一定的准确性和规范性。但由于视频数据的丰富内涵以及人们对视频内容进行抽取的主观性,视频信息难以用几个关键词描述。因此,基于内容的视频检索应运而生。

    传统的基于内容的视频检索方法是将视频作为帧图像的集合,运用图像检索的方法逐帧进行检索,这种方法的缺点是需要处理大量的图像信息,对信息传输和计算造成很大的困难。在视频帧序列中,包含有关键内容节点的帧可以简单的概括视频的主要内容,这些帧成为视频的关键帧,通过提取关键帧,可以极大的减少后续处理的数据量。

    技术实现要素:

    本发明提供一种视频关键帧提取算法,通过在各类视频的所有帧中提取出能够反映视频内容信息的关键帧,可以有效的降低视频分析时的数据量,提高视频处理效率。

    具体步骤如下:

    步骤一、针对当前的输入视频流中的某帧,经黑边检测模块计算得到水平方向的黑边宽度和垂直方向的黑边高度;

    具体计算过程如下:

    对输入视频流图像的上下边逐行检测黑边范围,计算得到每行黑边的高度,取高度最大值作为垂直方向上的黑边高度,对图像左右边逐列检测黑边范围,计算得到每列黑边的宽度,取宽度最大值作为水平方向的黑边宽度。

    步骤二、利用垂直方向的黑边高度和水平方向的黑边宽度,计算该帧有效图像区域的宽度和高度;

    具体计算如下:

    有效图像区域的起始点水平方向坐标等于水平方向黑边宽度,垂直方向的坐标等于垂直方向黑边高度,有效区域的宽度等于原图像宽减去两倍的水平方向黑边宽度,有效区域的高度等于原图像高减去两倍的垂直方向黑边高度。

    步骤三、将该帧的有效图像区域的长宽分别等分成16块,计算每块的Y值均值和UV差值的均值,并将256块区域的Y值均值和UV差值的均值作为该帧的特征信息。

    针对该帧的有效图像区域,将长宽均等分分割为16块,得到256块区域,分别计算每块的Y值均值和UV差值的均值,作为该帧的特征信息。

    步骤四、用帧差异比较模块将该帧的特征信息与前一帧的特征信息比较,并计算该帧的差异度;

    计算差异度的过程如下:

    步骤401、将两帧的256块区域一一对应,将每个区域中的Y值分别比较;

    步骤402、针对某对应区域块,将两个区域块中的Y值均值作差,得到差值绝对值;

    步骤403、计算该两个对应区域块中的Y值均值的平均值;

    步骤404、计算差值绝对值与平均值的比例,并判断比例值是否大于预设值,如果是,定义该区域块的差异值为1,否则该区域块的差异值为0;

    步骤405、针对该帧,利用256个区域块的差异值加权得到该帧的差异度。

    256个区域块中每个区域块对应各自的权值;

    步骤五、判断该帧的差异度是否大于阈值;如果是,则该帧视为差异帧,进入步骤六;否则该帧视为无差异帧,进入步骤八;

    步骤六、将该差异帧中的数据与缓存区中的每帧数据分别比较,计算该帧的相似度;

    计算相似度的过程如下:

    步骤601、选择缓存区域中的某帧,将该差异帧与该某帧做比较,将256个区域中的Y值分别比较;

    步骤602、针对某对应区域块,将两个区域块中的Y值均值作差,得到差值绝对值;

    步骤603、计算该两个对应区域块中的Y值均值的平均值;

    步骤604、计算差值绝对值与平均值的比例,并判断比例值是否小于预设值,如果是,定义该区域块的相似值为1,否则该区域块的相似值为0;

    步骤605、针对该差异帧,利用256个区域块的相似值加权得到该帧的相似度。

    256个区域块中每个区域块对应各自的权值;

    步骤七、判断该差异帧的相似度是否大于阈值,如果是,则将该差异帧与缓存区中的该某帧视为相似,进入步骤八;否则,将该差异帧的数据写入到缓存区,并输出该帧存在差异。

    步骤八、将非差异帧计数加1,并判断计数是否达到非差异帧累计数最大值,如果是,输出该帧为差异帧并写入缓存区,进入步骤九;否则,输出该帧为无差异帧。

    步骤九、利用空白帧检测模块分别统计该帧的Y值的方差值和UV值的方差值,并输出关键帧和空白帧;

    首先,统计256块区域的Y值的方差值,并判断该方差值是否大于阈值,如果是,则将该帧视为关键帧输出;否则,统计256块区域的UV值的方差值,判断该方差值是否大于阈值,如果是,则将该帧视为关键帧输出,否则,将该帧视为空白帧输出。

    本发明的优点及带来的有益效果在于:本发明所有模块均通过C语言实现,可应用于多视频多线程的调用,适应性强,高效快速。

    附图说明

    图1为本发明视频关键帧提取算法的整体结构图;

    图2为本发明视频关键帧提取算法的流程图;

    图3为本发明的黑边检测模块结构图;

    图4为本发明的空白帧检测模块结构图。

    具体实施方式

    下面结合附图对本发明的技术方案进行详细说明。

    本发明一种视频关键帧提取算法的整体结构,如图1所示,对于当前的输入视频流中的某帧,经过黑边检测模块计算该帧的特征信息,然后经帧差异比较模块判断是否存在差异,如果是,进一步经过空白帧检测模块区分关键帧或非关键帧,否则,直接将无差异帧输出为非关键帧,最终得到视频流中的该帧是否为关键帧。

    具体地,如图2所示,本发明的实施步骤如下:

    步骤一、针对当前的输入视频流中的某帧,经黑边检测模块计算得到水平方向的黑边宽度和垂直方向的黑边高度;

    黑边检测模块具体运算过程,如图3所示,如下:

    针对输入视频流图像,逐行遍历上边缘像素点,直至检测到非黑边,计算出上边缘到非黑边之间的距离;同理,逐行遍历下边缘像素点,直至检测到非黑边,计算出下边缘到非黑边之间的距离;取两距离中的最大值作为上下边的黑边高度,图像的宽度作为黑边的宽度;

    逐列遍历左边缘像素点,直至检测到非黑边,计算出左边缘到非黑边之间的距离;同理,逐列遍历右边缘像素点,直至检测到非黑边,计算出右边缘到非黑边之间的距离;取两距离中的最大值作为左右边的黑边宽度,图像的高度作为黑边的宽度;

    步骤二、利用垂直方向的黑边高度和水平方向的黑边宽度,计算该帧有效图像区域的宽度和高度;

    具体计算如下:

    有效图像区域的起始点水平方向坐标等于水平方向黑边宽度,垂直方向的坐标等于垂直方向黑边高度,有效区域的宽度等于原图像宽减去两倍的水平方向黑边宽度,有效区域的高度等于原图像高减去两倍的垂直方向黑边高度。

    步骤三、将该帧的有效图像区域的长宽分别等分成16块,计算每块的Y值均值和UV差值的均值,并将256块区域的Y值均值和UV差值的均值作为该帧的特征信息。

    针对该帧计算后的有效图像区域进行长宽16*16等分分割,得到256块区域,分别计算每块的Y值均值和UV差值的均值,作为该帧的特征信息。

    步骤四、用帧差异比较模块将该帧的特征信息与前一帧的特征信息比较,并计算该帧的差异度;

    计算差异度的过程如下:

    步骤401、将两帧的256块区域一一对应,将每个区域中的Y值分别比较;

    步骤402、针对某对应区域块,将两个区域块中的Y值均值作差,得到差值绝对值;

    步骤403、计算该两个对应区域块中的Y值均值的平均值;

    步骤404、计算差值绝对值与平均值的比例,并判断比例值是否大于预设值,如果是,定义该区域块的差异值为1,否则该区域块的差异值为0;

    步骤405、针对该帧,利用256个区域块的差异值加权得到该帧的差异度。

    256个区域块中每个区域块对应各自的权值;

    步骤五、判断该帧的差异度是否大于阈值;如果是,则该帧视为差异帧,进入步骤六;否则该帧视为无差异帧,进入步骤八;

    步骤六、将该差异帧中的数据与缓存区中的每帧数据分别比较,计算该帧的相似度;

    计算相似度的过程如下:

    步骤601、选择缓存区域中的某帧,将该差异帧与该某帧做比较,将256个区域中的Y值分别比较;

    步骤602、针对某对应区域块,将两个区域块中的Y值均值作差,得到差值绝对值;

    步骤603、计算该两个对应区域块中的Y值均值的平均值;

    步骤604、计算差值绝对值与平均值的比例,并判断比例值是否小于预设值,如果是,定义该区域块的相似值为1,否则该区域块的相似值为0;

    步骤605、针对该差异帧,利用256个区域块的相似值加权得到该帧的相似度。

    256个区域块中每个区域块对应各自的权值;

    步骤七、判断该差异帧的相似度是否大于阈值,如果是,则将该差异帧与缓存区中的该某帧视为相似,进入步骤八;否则,将该差异帧的数据写入到缓存区,并输出该帧存在差异。

    步骤八、将非差异帧计数加1,并判断计数是否达到非差异帧累计数最大值,如果是,输出该帧为差异帧并写入缓存区,进入步骤九;否则,输出该帧为无差异帧。

    步骤九、利用空白帧检测模块分别统计该帧的Y值的方差值和UV值的方差值,并输出关键帧和空白帧;

    如图4所示,首先,统计256块区域的Y值的方差值,并判断该方差值是否大于阈值,如果是,则将该帧视为关键帧输出;否则,继续统计256块区域的UV值的方差值,判断该方差值是否大于阈值,如果是,则将该帧视为关键帧输出,否则,将该帧视为空白帧输出。

    展开全文
  • 针对煤矿井下特殊的监控环境,对基于帧差欧氏距离的关键帧提取算法进行了研究。针对该算法存在的关键帧冗余度较大的问题,利用Canny算法提取图像边缘并进行边缘匹配,将冗余的关键帧剔除,从而降低冗余度。理论分析和...
  • 针对基于内容的视频检索系统,提出了一种关键帧提取算法。为了提高算法的保真度和压缩比,首先构造了动态帧,它的每个像素对应一个像素代表灰度集合,该集合中的元素可以最大限度地代表镜头中相应像素的灰度值,然后根据...
  • 利用Python对视频进行关键帧提取
  • 针对运动类视频特征不易提取且其关键帧结果中易产生较多漏检帧的问题,提出基于运动目标特征的关键帧提取算法。该算法在强调运动目标特征的同时弱化背景特征,从而防止由于运动目标过小而背景占据视频画面主要内容所...
  • 针对这些缺陷,研究了基于聚类的自适应关键帧提取算法,在此基础上,提出基于互信息量的改进算法。最后,针对以上2种算法中的时延问题给出了解决方案。实验证明,对于不同的测试序列,基于互信息量改进算法相比固定选取...
  • 针对运动视频关键帧提取结果运动表达能力差的问题,以健美操运动视频关键帧提取为例,将先验语义引入到视频片段分割和关键帧提取特征提取等过程中,提出基于先验的运动视频关键帧提取算法。该算法采用韵律特征和动作...
  • 视频关键帧提取源码

    热门讨论 2012-09-06 11:07:04
    基于互信息量、聚类等的视频关键帧提取算法,在vc6.0下编译通过。
  • 10TB点播流量包仅需999元,参与活动还赠移动直播SDK,短视频SDK,小程序插件等,大促100%中奖率我记得之前我粗略写过i帧的判断:h264编码nalu结构介绍与i帧判断方法,但也是粗略的写了一下,本篇文章我决定就关键帧来...

    q298skpf9u.png广告关闭

    100GB直播流量包仅需9.9元,10TB点播流量包仅需999元,参与活动还赠移动直播SDK,短视频SDK,小程序插件等,大促100%中奖率

    我记得之前我粗略写过i帧的判断:h264编码nalu结构介绍与i帧判断方法,但也是粗略的写了一下,本篇文章我决定就关键帧来做个详细点的说明,最基本的就是——什么是关键帧。 关键帧,就是说这一帧是连接两段不同的内容,这一帧后面的视频内容会有新的变化或过渡; 在时间轴上这一帧带有小黑点标志; 空白关键帧,跟...

    o8vx5wsaal.png

    问题描述:使用opencv把avi视频切分成静态图像,提取视频中的关键帧,保存为0.jpg、1.jpg、2.jpg..... 实现步骤:1)安装扩展库? 2)准备一个avi视频,这里以微课系列(5):python程序中__name__变量的用法中录制的视频为例。 3)编写代码,分离视频,保存静态图像。? 4)查看结果?...

    转码时长:转码时长指【开始转码时间】之后的转码时间长度,提供【原视频时长】和【自定义】两种时长选择。 抽帧方式抽取全部帧:抽取视频的每一帧。 抽帧频率:您可设定每秒钟抽取帧的数量,可输入1-50内的整数。 抽帧间隔:每隔指定秒数抽取1帧。 仅提取关键帧:通过对视频内容的理解,利用 ai 智能识别抽取最优帧...

    9h1vhkdrno.gif

    由于视频数据与图像数据的相似性,在上述列举的视频领域任务中大都可以借助图像方法来完成。 文本将讲解视频抽帧的几种方法,具体包括以下几种抽帧方式:抽取视频关键帧(ipb帧)抽取视频场景转换帧按照时间进行均匀抽帧抽取制定时间的视频帧在进行讲解具体的抽帧方式之前,我不得不介绍下ffmpeg。 ffmpeg是一套可以...

    并且支持客户自定义关键词且定位出关键词所在视频的时间点 支持实时流语音识别分析语音识别 文字识别 文字识别 快速识别视频中出现的文字信息 简体 繁体 英文等可用于视频内的自定义关键词的提取 也支持竖版文字的识别支持客户自定义关键词且定位出关键词所在视频的时间点 文字识别 帧标签识别帧标签识别 支持自定义...

    还结合腾讯云先进的 技术 通过对视频内容的理解智能计算选出最优的关键帧作为视频封面 可以有效提升视频点击率及用户视觉体验客户案例 开始使用腾讯云数据...规避违规风险 针对有大量 及 视频内容的电商 社交平台 在线教育 视频网站等领域数据万象 提供视频截帧 视频转动图 视频元信息提取等基础视频处理服务 此外...

    媒体处理数据万象 ci 提供视频截帧、视频转动图、视频元信息提取等基础视频处理服务。 此外,还结合腾讯云先进的 ai 技术,通过对视频内容的理解,智能计算选出最优的关键帧作为视频封面,可以有效提升视频点击率及用户视觉体验。 文档服务支持多种类型的文件生成图片预览,可以解决文档内容的页面展示问题...

    提取最优帧生成截图作为封面,提升内容吸引力。 说明: 智能封面是付费服务,按照视频时长进行计费,具体费用请参见 媒体处理费用。 数据万象为每个账户提供每月500分钟的免费体验额度,超出后将正常计费。 未使用额度不会累积至下一月。 每个视频文件将智能分析输出3张最优的关键帧。 功能体验您可在线体验智能封面...

    每个视频文件将智能分析输出3张最优的关键帧。 数据万象也提供创建任务接口,可以根据参数进行配置,详情请参考 createmediajobs api 文档。 操作步骤登录...创建智能封面任务智能封面功能集成腾讯云音视频实验室先进的 ai 技术,通过对视频内容的理解,智能分析视频帧的质量、精彩程度、内容相关度,提取最优帧...

    rnycegprxz.jpeg

    提取关键点此前被视为需要大量数据才能完成的工作,但deepmind的一项最新研究可不这么认为。 deepmind的新模型transporter从原始视频帧中学习以物体为中心的抽象表示,并能用简单的算法生成控制策略和探索程序。 也就是说,用无监督的方法和寥寥数据,就能提取出关键点,在没有奖励的情况下,还能进行有效操控...

    frameinterval否integer视频处理的抽帧间隔,单位毫秒。 建议留空。 keywordslanguage否integer关键词语言类型,0为英文,1为中文。 keywordsstrings.n否...invalidparameter.featureextractionfailed特征提取失败invalidparameter.filecontentempty输入内容为空invalidparameter.imagedecodefailed输入图片无法...

    语音识别基于深度学习方案,帮助客户快速识别视频中的声音并转化成文字,支持客户自定义关键词且定位出关键词所在视频的时间点。 文字识别帮助客户识别视频中出现的文字信息,可用于视频内自定义关键词的提取,也支持竖版文字的识别。 帧标签识别基于深度学习方案,支持根据客户自定义视频截帧间隔,自动识别截帧画面...

    语音识别快速识别视频中的声音并转化成文字,支持客户自定义关键词且定位出关键词所在视频的时间点。 文字识别识别视频中出现的文字信息,可用于视频内自定义关键词的提取,也支持竖版文字的识别。 帧标签识别识别截帧画面内的标签,并定位标签所在的视频位置,帧标签涵盖人物、风景、人造物、建筑、动植物、食物等9...

    设备独自执行提取特征注册人脸 使用一台 设备专门用于提取特征然后通过服务器或者其他方式分发人脸特征到其他的 设备上 直接申请接入腾讯云人脸识别门禁...静态活体检测是否支持视频识别 只支持检测静态照片 建议将视频截帧识别静态活体检测可以应用在哪些场景中 建议用于对防攻击要求不高的场景对安全性要求高...

    mkz0knabeb.jpeg

    这基本上也呈现出了项目团队的大致思路:使用基于强化学习的关键帧提取算法,提取视频中有意义且有代表性的帧,然后对关键帧进行评估,确认主要的画面之后,再进行使用gan进行风格迁移,形成漫画风格。? 在风格迁移方面,研究团队对当前已经发表的漫画风格迁移模型进行了研究,最后基于cartoongan的方法,利用ms coco...

    vef2dbreih.jpeg

    在前段时间举行的 2018 年欧洲计算机视觉大会(eccv2018)上,周博磊与麻省理工学院的研究人员一共提出了一个附加的视频处理模块,该模块可以帮助被人们称为卷积神经网络(cnn)的人工智能系统填补视频帧之间的空白,从而大大提升了网络的活动识别能力。 机器学习系统通过仅仅在几个关键帧中观察物体如何变化从而有效...

    在本文中,我们描述了visione,一个视频搜索系统,它允许用户使用文本关键词、对象的出现及其空间关系、颜色的出现及其空间关系还有图像的相似性来搜索视频。 这些模式可以组合在一起来表达复杂的查询并满足用户的需求。 我们的方法的特点是,我们从关键帧提取的所有信息编码,如视觉深度特征,标签,颜色和目标位置...

    erx8djyxbb.jpeg

    例如,对于视频,首先进行镜头分割和关键帧提取,然后分发到镜头检索、片断检索、概念检测、视觉目标检测、人脸识别和视频字幕识别等模块。 基于多模态信息的分发结果,对各模态内容分别进行分析与识别,提取文本、图像、视频镜头、视频片断、视觉对象(如视觉目标、人脸)等语义描述信息。 进一步对多模态数据进行...

    yczr88r3gv.jpeg

    在关键地方写文件或者打日志,通过专业音视频分析工具,把问题定位到模块内部或者模块之间的边界上。 模块内部一般分析代码对码流的具体处理,模块之间...假设参考帧丢掉,后面p帧播放就会出现花屏,同时再用streameye工具分析这个ts的确如此:? 工具分析发现每个gop里面只有43帧,和设备端配置的50帧一个gop...

    8bg2ufmgvb.png

    下面为作者信息:? 视频动作定位是在视频中定位出正在执行动作的主体并识别出动作的问题。 请看下面这幅动图:? 很显然该问题包括:在多帧中定位主体和动作分类。 在对关键帧(当前帧)进行动作分类时,很显然要考虑之前的数据。 ?作者提出的算法正是在这一观察下, 结合3d-cnn 提取时空信息和2d cnn 提取位置信息再...

    展开全文
  • 基于子镜头分割的自适应关键帧提取算法,段豪,谢刚,关键帧的提取是基于内容的视频检索的重要技术,它也是视频分析和基于高级语义的视频检索的基础。本文提出了一种基于子镜头分割的
  • 针对实时、大词汇集、连续的手语视频高效准确地识别,提出了一种基于压缩感知与加速稳健特征(SURF)的手语关键帧提取算法。利用压缩感知将手语视频降维成低维多尺度帧图像特征,通过自适应阈值完成子镜头分割,以处理...
  • 一种改进的无监督聚类的关键帧提取算法 主要用在视频检索中
  • 为了有效、且自适应的提取视频中的关键帧,提出了一种改进的三维蚁堆新算法。该算法首先提取每一帧中H-S-V颜色空间的三维特征向量,并将其表示为H-S-V三维欧式空间中的点,之后通过改进的三维蚁堆算法,自适应的聚类,...
  • 基于GEP自动聚类算法视频关键帧提取方法.pdf
  • 提出了一种危险源监控视频关键帧提取算法。根据危险源监控视频的特点,利用I帧DC图的比较,减少危险源监控视频的冗余信息,获取有效视频;利用基于镜头的压缩域关键帧提取方法提取帧。实验结果表明,该方法能有效...
  • python实现视频关键帧提取(基于帧间差分)

    万次阅读 多人点赞 2018-12-05 20:35:17
    python实现视频关键帧提取(基于帧间差分) 在很多场景下,我们不想或者不能处理视频的每一帧图片,这时我们希望能够从视频中提取出一些重要的帧进行处理,这个过程我们称为视频关键帧提取关键帧提取算法多种多样...

    python实现视频关键帧提取(基于帧间差分)

    在很多场景下,我们不想或者不能处理视频的每一帧图片,这时我们希望能够从视频中提取出一些重要的帧进行处理,这个过程我们称为视频关键帧提取。

    关键帧提取算法多种多样,如何实现主要取决于你对于关键帧的定义。

    也就是说,对于你的实际应用场景,视频中什么样的图片才算是一个关键帧?

    今天我实现了一种比较通用的关键帧提取算法,它基于帧间差分。

    算法的原理很简单:我们知道,将两帧图像进行差分,得到图像的平均像素强度可以用来衡量两帧图像的变化大小。因此,基于帧间差分的平均强度,每当视频中的某一帧与前一帧画面内容产生了大的变化,我们便认为它是关键帧,并将其提取出来。

    算法的流程简述如下:

    首先,我们读取视频,并依次计算每两帧之间的帧间差分,进而得到平均帧间差分强度。

    然后,我们可以选择如下的三种方法的一种来提取关键帧,它们都是基于帧间差分的:

    1. 使用差分强度的顺序

      我们对所有帧按照平均帧间差分强度进行排序,选择平均帧间差分强度最高的若干张图片作为视频的关键帧。

    2. 使用差分强度阈值

      我们选择平均帧间差分强度高于预设阈值的帧作为视频的关键帧。

    3. 使用局部最大值

      我们选择具有平均帧间差分强度局部最大值的帧作为视频的关键帧。

      这种方法的提取结果在丰富度上表现更好一些,提取结果均匀分散在视频中。

      需要注意的是,使用这种方法时,对平均帧间差分强度时间序列进行平滑是很有效的技巧。它可以有效的移除噪声来避免将相似场景下的若干帧均同时提取为关键帧。

    这里比较推荐使用第三种方法来提取视频的关键帧

    获取源码点这里

    最初的代码来自于这里, 但是其代码本身有些问题,在读取超过100M的视频时程序会出现内存溢出的错误,因此我对其进行了优化,减去了不必要的内存消耗。

    精灵宝可梦的一个经典片段中进行了实验,平滑后的平均帧间差分强度如下图所示:

    plot

    提取的部分关键帧如下所示:

    fftsiftsift
    fftsiftsift
    fftsiftsift

    效果还不错吧~

    我这里仅仅是对视频关键帧提取的方法进行了简单的探索,最终得到的效果也满足了我实际工作的需要。如果您对视频关键帧提取领域很了解,或者了解其他更好的方法,期待与您交流~

    最后,对算法感兴趣的小伙伴,欢迎关注我的github项目AI-Toolbox

    此项目旨在提高效率,快速迭代新想法,欢迎贡献代码~

    展开全文
  • 如题,好像OpenCV里没有封装好的函数,有没有做过的朋友知道的?或者提取关键帧算法
  • 基于K-means聚类算法视频关键帧提取的研究.pdf
  • 将相关向量机理论应用于视频关键帧语义提取。该方法把关键帧中的HSV颜色直方图、MPEG-7边缘直方图和灰度共生矩阵相结合,建立特征标定向量集;基于图分割模型对二叉树多分类器结构进行优化,构建最优二叉树语义多...
  • 针对视频关键帧提取问题,提出了一种密度峰值聚类算法,该算法利用HSV直方图将高维抽象视频图像数据转换为可量化的低维数据,并降低了捕获图像特征时的计算复杂度。 在此基础上,使用密度峰值聚类算法对这些低维数据...
  • 针对目前压缩域下提取视频关键帧的算法存在特征选取单一、提取的关键帧准确性不高、算法效率低的缺点,提出了压缩域下基于两次曲线曲率检测的关键帧提取算法。算法利用曲线上的高曲率点表示曲线的显著变化,并在此...
  • 视频提取关键帧提取

    千次阅读 2020-11-09 16:52:36
    视频提取关键帧提取 文章目录视频提取关键帧提取前言一、什么是关键帧和为什么要提取...视频关键帧提取则主要体现视频中各个镜头的显著特征,通过视频关键帧提取能够有效减少视频检索所需要花费的时间,并能够增强视

    视频提取关键帧提取

    前言

    正所谓做工作要做好记录,现在,我要开始记录啦。

    一、什么是关键帧和为什么要提取关键帧?

    1、每个视频都是一个图像序列,其内容比一张图像丰富很多,表现力强,信息量大。对视频的分析通常是基于视频帧,但视频帧通常存在大量冗余,对视频帧的提取也存在漏帧、冗余的现象。视频关键帧提取则主要体现视频中各个镜头的显著特征,通过视频关键帧提取能够有效减少视频检索所需要花费的时间,并能够增强视频检索的精确度。

    2、关键帧定义:把图像坐标系中每个“视频帧”都叠加在一起,这时镜头中视频帧的特征矢量会在空间中呈现出一个轨迹的状态,而与轨迹中特征值进行对应的“帧”即可称之为关键帧[1]

    3、视频具有层次化结构,由场景、镜头和帧三个逻辑单元组成。视频检索常基于帧进行,因此,提取视频的关键帧至关重要[2]

    二、关键帧提取方法

    1、关键帧提取思想:对视频序列采用镜头分割的方式,然后在镜头当中获得内容关键帧提取,接着利用“关键帧”来获得底层的形状、纹理和颜色等特征。

    2、关键帧提取方法:

    (1)全图像序列

    ​ 镜头边界方法是将镜头中的第一帧和最后一帧(或中间帧)作为关键帧。该方法简单易行,适于内容活动性小或内容保持不变的镜头,但未考虑镜头视觉内容的复杂性,限制了镜头关键帧的个数,提取的关键帧代表性不强,效果不够稳定。

    (2)压缩视频

    (3) 自定义k值聚类和内容分析的关键帧提取方法[2]

    (4)a 基于抽样的关键帧提取[3]

    ​ 基于抽样的方法是通过随机抽取或在规定的时间间隔内随机抽取视频帧。这种方法简单不实用。

    ​ b 基于颜色特征的关键帧提取

    ​ c 基于运动分析的关键帧提取

    ​ d 基于镜头边界的关键帧提取(*)

    	e 基于视频内容的关键帧提取(*)
    

    ​ f 基于聚类的关键帧提取 (可能是最合适的一个了),我要识别的类别已经确定。

    (5)使用3D-CNN提取关键帧[4]

    ​ 他提出了一种基于语义的视频关键帧提取算法,该算法首先使用层次聚类算法对视频关键帧进行初步提取;然后结合语义相关算法对初步提取的关键帧进行直方图对比去掉冗余帧,确定视频的关键帧;最后通过与其他算法比较,本文提出的算法提取的关键帧冗余度相对小。

    (6)首先利用卷积自编码器提取视频帧的深度特征,对其进行 K-means 聚类,在每类视频帧中采用清晰度筛选取出最清晰的视频帧作为初次提取的关键帧;然后利用点密度方法对初次提取的关键帧进行二次优化,得到最终提取的关键帧进行手语识别.[5]

    (7) 视频关键帧提取方法一般可分为四大类:

    ​ 第一类:基于图像内容的方法

    ​ 第二类:基于运动分析的方法

    ​ 第三类:基于轨迹曲线点密度特征的关键帧检测算法

    ​ 第四类:目前主流方法:基于聚类的方法

    (8)帧间差法

    ​ 源自: 以下代码出自zyb_as的github

    # -*- coding: utf-8 -*-
    """
    帧间最大值法
    Created on Tue Dec  4 16:48:57 2018
    keyframes extract tool
    this key frame extract algorithm is based on interframe difference.
    The principle is very simple
    First, we load the video and compute the interframe difference between each frames
    Then, we can choose one of these three methods to extract keyframes, which are 
    all based on the difference method:
        
    1. use the difference order
        The first few frames with the largest average interframe difference 
        are considered to be key frames.
    2. use the difference threshold
        The frames which the average interframe difference are large than the 
        threshold are considered to be key frames.
    3. use local maximum
        The frames which the average interframe difference are local maximum are 
        considered to be key frames.
        It should be noted that smoothing the average difference value before 
        calculating the local maximum can effectively remove noise to avoid 
        repeated extraction of frames of similar scenes.
    After a few experiment, the third method has a better key frame extraction effect.
    The original code comes from the link below, I optimized the code to reduce 
    unnecessary memory consumption.
    https://blog.csdn.net/qq_21997625/article/details/81285096
    @author: zyb_as
    """ 
    import cv2
    import operator
    import numpy as np
    import matplotlib.pyplot as plt
    import sys
    from scipy.signal import argrelextrema
    
     
    def smooth(x, window_len=13, window='hanning'):
        """smooth the data using a window with requested size.
        
        This method is based on the convolution of a scaled window with the signal.
        The signal is prepared by introducing reflected copies of the signal 
        (with the window size) in both ends so that transient parts are minimized
        in the begining and end part of the output signal.
        
        input:
            x: the input signal 
            window_len: the dimension of the smoothing window
            window: the type of window from 'flat', 'hanning', 'hamming', 'bartlett', 'blackman'
                flat window will produce a moving average smoothing.
        output:
            the smoothed signal
            
        example:
        import numpy as np    
        t = np.linspace(-2,2,0.1)
        x = np.sin(t)+np.random.randn(len(t))*0.1
        y = smooth(x)
        
        see also: 
        
        numpy.hanning, numpy.hamming, numpy.bartlett, numpy.blackman, numpy.convolve
        scipy.signal.lfilter
     
        TODO: the window parameter could be the window itself if an array instead of a string   
        """
        print(len(x), window_len)
        # if x.ndim != 1:
        #     raise ValueError, "smooth only accepts 1 dimension arrays."
        #
        # if x.size < window_len:
        #     raise ValueError, "Input vector needs to be bigger than window size."
        #
        # if window_len < 3:
        #     return x
        #
        # if not window in ['flat', 'hanning', 'hamming', 'bartlett', 'blackman']:
        #     raise ValueError, "Window is on of 'flat', 'hanning', 'hamming', 'bartlett', 'blackman'"
     
        s = np.r_[2 * x[0] - x[window_len:1:-1],
                  x, 2 * x[-1] - x[-1:-window_len:-1]]
        #print(len(s))
     
        if window == 'flat':  # moving average
            w = np.ones(window_len, 'd')
        else:
            w = getattr(np, window)(window_len)
        y = np.convolve(w / w.sum(), s, mode='same')
        return y[window_len - 1:-window_len + 1]
     
    
    class Frame:
        """class to hold information about each frame
        
        """
        def __init__(self, id, diff):
            self.id = id
            self.diff = diff
     
        def __lt__(self, other):
            if self.id == other.id:
                return self.id < other.id
            return self.id < other.id
     
        def __gt__(self, other):
            return other.__lt__(self)
     
        def __eq__(self, other):
            return self.id == other.id and self.id == other.id
     
        def __ne__(self, other):
            return not self.__eq__(other)
     
     
    def rel_change(a, b):
       x = (b - a) / max(a, b)
       print(x)
       return x
     
        
    if __name__ == "__main__":
        print(sys.executable)
        #Setting fixed threshold criteria
        USE_THRESH = False
        #fixed threshold value
        THRESH = 0.6
        #Setting fixed threshold criteria
        USE_TOP_ORDER = False
        #Setting local maxima criteria
        USE_LOCAL_MAXIMA = True
        #Number of top sorted frames
        NUM_TOP_FRAMES = 50
         
        #Video path of the source file
        videopath = 'pikachu.mp4'
        #Directory to store the processed frames
        dir = './extract_result/'
        #smoothing window size
        len_window = int(50)
        
        
        print("target video :" + videopath)
        print("frame save directory: " + dir)
        # load video and compute diff between frames
        cap = cv2.VideoCapture(str(videopath)) 
        curr_frame = None
        prev_frame = None 
        frame_diffs = []
        frames = []
        success, frame = cap.read()
        i = 0 
        while(success):
            luv = cv2.cvtColor(frame, cv2.COLOR_BGR2LUV)
            curr_frame = luv
            if curr_frame is not None and prev_frame is not None:
                #logic here
                diff = cv2.absdiff(curr_frame, prev_frame)
                diff_sum = np.sum(diff)
                diff_sum_mean = diff_sum / (diff.shape[0] * diff.shape[1])
                frame_diffs.append(diff_sum_mean)
                frame = Frame(i, diff_sum_mean)
                frames.append(frame)
            prev_frame = curr_frame
            i = i + 1
            success, frame = cap.read()   
        cap.release()
        
        # compute keyframe
        keyframe_id_set = set()
        if USE_TOP_ORDER:
            # sort the list in descending order
            frames.sort(key=operator.attrgetter("diff"), reverse=True)
            for keyframe in frames[:NUM_TOP_FRAMES]:
                keyframe_id_set.add(keyframe.id) 
        if USE_THRESH:
            print("Using Threshold")
            for i in range(1, len(frames)):
                if (rel_change(np.float(frames[i - 1].diff), np.float(frames[i].diff)) >= THRESH):
                    keyframe_id_set.add(frames[i].id)   
        if USE_LOCAL_MAXIMA:
            print("Using Local Maxima")
            diff_array = np.array(frame_diffs)
            sm_diff_array = smooth(diff_array, len_window)
            frame_indexes = np.asarray(argrelextrema(sm_diff_array, np.greater))[0]
            for i in frame_indexes:
                keyframe_id_set.add(frames[i - 1].id)
                
            plt.figure(figsize=(40, 20))
            plt.locator_params(numticks=100)
            plt.stem(sm_diff_array)
            plt.savefig(dir + 'plot.png')
        
        # save all keyframes as image
        cap = cv2.VideoCapture(str(videopath))
        curr_frame = None
        keyframes = []
        success, frame = cap.read()
        idx = 0
        while(success):
            if idx in keyframe_id_set:
                name = "keyframe_" + str(idx) + ".jpg"
                cv2.imwrite(dir + name, frame)
                keyframe_id_set.remove(idx)
            idx = idx + 1
            success, frame = cap.read()
        cap.release()
    

    运动分析流光法进行关键帧提取

    源自:AillenAnthony的github

    # Scripts to try and detect key frames that represent scene transitions
    # in a video. Has only been tried out on video of slides, so is likely not
    # robust for other types of video.
    
    # 1. 基于图像信息
    # 2. 基于运动分析(光流分析)
    
    import cv2
    import argparse
    import json
    import os
    import numpy as np
    import errno
    
    def getInfo(sourcePath):
        cap = cv2.VideoCapture(sourcePath)
        info = {
            "framecount": cap.get(cv2.CAP_PROP_FRAME_COUNT),
            "fps": cap.get(cv2.CAP_PROP_FPS),
            "width": int(cap.get(cv2.CAP_PROP_FRAME_WIDTH)),
            "heigth": int(cap.get(cv2.CAP_PROP_FRAME_Heigth)),
            "codec": int(cap.get(cv2.CAP_PROP_FOURCC))
        }
        cap.release()
        return info
    
    
    def scale(img, xScale, yScale):
        res = cv2.resize(img, None,fx=xScale, fy=yScale, interpolation = cv2.INTER_AREA)
        return res
    
    def resize(img, width, heigth):
        res = cv2.resize(img, (width, heigth), interpolation = cv2.INTER_AREA)
        return res
    
    #
    # Extract [numCols] domninant colors from an image
    # Uses KMeans on the pixels and then returns the centriods
    # of the colors
    #
    def extract_cols(image, numCols):
        # convert to np.float32 matrix that can be clustered
        Z = image.reshape((-1,3))
        Z = np.float32(Z)
    
        # Set parameters for the clustering
        max_iter = 20
        epsilon = 1.0
        K = numCols
        criteria = (cv2.TERM_CRITERIA_EPS + cv2.TERM_CRITERIA_MAX_ITER, max_iter, epsilon)
        labels = np.array([])
        # cluster
        compactness, labels, centers = cv2.kmeans(Z, K, labels, criteria, 10, cv2.KMEANS_RANDOM_CENTERS)
    
        clusterCounts = []
        for idx in range(K):
            count = len(Z[labels == idx])
            clusterCounts.append(count)
    
        #Reverse the cols stored in centers because cols are stored in BGR
        #in opencv.
        rgbCenters = []
        for center in centers:
            bgr = center.tolist()
            bgr.reverse()
            rgbCenters.append(bgr)
    
        cols = []
        for i in range(K):
            iCol = {
                "count": clusterCounts[i],
                "col": rgbCenters[i]
            }
            cols.append(iCol)
    
        return cols
    
    
    #
    # Calculates change data one one frame to the next one.
    #
    def calculateFrameStats(sourcePath, verbose=False, after_frame=0):  # 提取相邻帧的差别
        cap = cv2.VideoCapture(sourcePath)#提取视频
    
        data = {
            "frame_info": []
        }
    
        lastFrame = None
        while(cap.isOpened()):
            ret, frame = cap.read()
            if frame == None:
                break
    
            frame_number = cap.get(cv2.CAP_PROP_POS_FRAMES) - 1
    
            # Convert to grayscale, scale down and blur to make
            # calculate image differences more robust to noise
            gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)      # 提取灰度信息
            gray = scale(gray, 0.25, 0.25)      # 缩放为原来的四分之一
            gray = cv2.GaussianBlur(gray, (9,9), 0.0)   # 做高斯模糊
    
            if frame_number < after_frame:
                lastFrame = gray
                continue
    
    
            if lastFrame != None:
    
                diff = cv2.subtract(gray, lastFrame)        # 用当前帧减去上一帧
    
                diffMag = cv2.countNonZero(diff)        # 计算两帧灰度值不同的像素点个数
    
                frame_info = {
                    "frame_number": int(frame_number),
                    "diff_count": int(diffMag)
                }
                data["frame_info"].append(frame_info)
    
                if verbose:
                    cv2.imshow('diff', diff)
                    if cv2.waitKey(1) & 0xFF == ord('q'):
                        break
    
            # Keep a ref to this frame for differencing on the next iteration
            lastFrame = gray
    
        cap.release()
        cv2.destroyAllWindows()
    
        #compute some states
        diff_counts = [fi["diff_count"] for fi in data["frame_info"]]
        data["stats"] = {
            "num": len(diff_counts),
            "min": np.min(diff_counts),
            "max": np.max(diff_counts),
            "mean": np.mean(diff_counts),
            "median": np.median(diff_counts),
            "sd": np.std(diff_counts)   # 计算所有帧之间, 像素变化个数的标准差
        }
        greater_than_mean = [fi for fi in data["frame_info"] if fi["diff_count"] > data["stats"]["mean"]]
        greater_than_median = [fi for fi in data["frame_info"] if fi["diff_count"] > data["stats"]["median"]]
        greater_than_one_sd = [fi for fi in data["frame_info"] if fi["diff_count"] > data["stats"]["sd"] + data["stats"]["mean"]]
        greater_than_two_sd = [fi for fi in data["frame_info"] if fi["diff_count"] > (data["stats"]["sd"] * 2) + data["stats"]["mean"]]
        greater_than_three_sd = [fi for fi in data["frame_info"] if fi["diff_count"] > (data["stats"]["sd"] * 3) + data["stats"]["mean"]]
    
        # 统计其他信息
        data["stats"]["greater_than_mean"] = len(greater_than_mean)
        data["stats"]["greater_than_median"] = len(greater_than_median)
        data["stats"]["greater_than_one_sd"] = len(greater_than_one_sd)
        data["stats"]["greater_than_three_sd"] = len(greater_than_three_sd)
        data["stats"]["greater_than_two_sd"] = len(greater_than_two_sd)
    
        return data
    
    
    
    #
    # Take an image and write it out at various sizes.
    #
    # TODO: Create output directories if they do not exist.
    #
    def writeImagePyramid(destPath, name, seqNumber, image):
        fullPath = os.path.join(destPath, "full", name + "-" + str(seqNumber) + ".png")
        halfPath = os.path.join(destPath, "half", name + "-" + str(seqNumber) + ".png")
        quarterPath = os.path.join(destPath, "quarter", name + "-" + str(seqNumber) + ".png")
        eigthPath = os.path.join(destPath, "eigth", name + "-" + str(seqNumber) + ".png")
        sixteenthPath = os.path.join(destPath, "sixteenth", name + "-" + str(seqNumber) + ".png")
    
        hImage = scale(image, 0.5, 0.5)
        qImage = scale(image, 0.25, 0.25)
        eImage = scale(image, 0.125, 0.125)
        sImage = scale(image, 0.0625, 0.0625)
    
        cv2.imwrite(fullPath, image)
        cv2.imwrite(halfPath, hImage)
        cv2.imwrite(quarterPath, qImage)
        cv2.imwrite(eigthPath, eImage)
        cv2.imwrite(sixteenthPath, sImage)
    
    
    
    #
    # Selects a set of frames as key frames (frames that represent a significant difference in
    # the video i.e. potential scene chnges). Key frames are selected as those frames where the
    # number of pixels that changed from the previous frame are more than 1.85 standard deviations
    # times from the mean number of changed pixels across all interframe changes.
    #
    def detectScenes(sourcePath, destPath, data, name, verbose=False):
        destDir = os.path.join(destPath, "images")
    
        # TODO make sd multiplier externally configurable
        #diff_threshold = (data["stats"]["sd"] * 1.85) + data["stats"]["mean"]
        diff_threshold = (data["stats"]["sd"] * 2.05) + (data["stats"]["mean"])
    
        cap = cv2.VideoCapture(sourcePath)
        for index, fi in enumerate(data["frame_info"]):
            if fi["diff_count"] < diff_threshold:
                continue
    
            cap.set(cv2.CAP_PROP_POS_FRAMES, fi["frame_number"])
            ret, frame = cap.read()
    
            # extract dominant color
            small = resize(frame, 100, 100)
            cols = extract_cols(small, 5)
            data["frame_info"][index]["dominant_cols"] = cols
    
    
            if frame != None:
                writeImagePyramid(destDir, name, fi["frame_number"], frame)
    
                if verbose:
                    cv2.imshow('extract', frame)
                    if cv2.waitKey(1) & 0xFF == ord('q'):
                        break
    
        cap.release()
        cv2.destroyAllWindows()
        return data
    
    
    def makeOutputDirs(path):
        try:
            #todo this doesn't quite work like mkdirp. it will fail
            #fi any folder along the path exists. fix
            os.makedirs(os.path.join(path, "metadata"))
            os.makedirs(os.path.join(path, "images", "full"))
            os.makedirs(os.path.join(path, "images", "half"))
            os.makedirs(os.path.join(path, "images", "quarter"))
            os.makedirs(os.path.join(path, "images", "eigth"))
            os.makedirs(os.path.join(path, "images", "sixteenth"))
        except OSError as exc: # Python >2.5
            if exc.errno == errno.EEXIST and os.path.isdir(path):
                pass
            else: raise
    
    
    if __name__ == '__main__':
    
        parser = argparse.ArgumentParser()
    
        # parser.add_argument('-s','--source', help='source file', required=True)
        # parser.add_argument('-d', '--dest', help='dest folder', required=True)
        # parser.add_argument('-n', '--name', help='image sequence name', required=True)
        # parser.add_argument('-a','--after_frame', help='after frame', default=0)
        # parser.add_argument('-v', '--verbose', action='store_true')
        # parser.set_defaults(verbose=False)
    
        parser.add_argument('-s','--source', help='source file', default="dataset/video/wash_hand/00000.mp4")
        parser.add_argument('-d', '--dest', help='dest folder', default="dataset/video/key_frame")
        parser.add_argument('-n', '--name', help='image sequence name', default="")
        parser.add_argument('-a','--after_frame', help='after frame', default=0)
        parser.add_argument('-v', '--verbose', action='store_true')
        parser.set_defaults(verbose=False)
    
        args = parser.parse_args()
    
        if args.verbose:
            info = getInfo(args.source)
            print("Source Info: ", info)
    
        makeOutputDirs(args.dest)
    
        # Run the extraction
        data = calculateFrameStats(args.source, args.verbose, int(args.after_frame))
        data = detectScenes(args.source, args.dest, data, args.name, args.verbose)
        keyframeInfo = [frame_info for frame_info in data["frame_info"] if "dominant_cols" in frame_info]
    
        # Write out the results
        data_fp = os.path.join(args.dest, "metadata", args.name + "-meta.json")
        with open(data_fp, 'w') as f:
            data_json_str = json.dumps(data, indent=4)
            f.write(data_json_str)
    
        keyframe_info_fp = os.path.join(args.dest, "metadata", args.name + "-keyframe-meta.json")
        with open(keyframe_info_fp, 'w') as f:
            data_json_str = json.dumps(keyframeInfo, indent=4)
            f.write(data_json_str)
    

    (9) 使用ffmpeg进行关键帧提取

    代码见于此处

    (10) 使用K-means聚类法

    源代码见于此处

    filenames=dir('images/*.jpg');
    %file_name = fly-1;
    num=size(filenames,1);  %输出filenames中文件图片的个数
    key=zeros(1,num);  %一行,num列都是0  [0,0,0,0,0,0,0,0,0,0,0,0,....0,0,0,0]
    cluster=zeros(1,num);   %[0,0,0,0,0,0,0,0,0,0,0,0,....0,0,0,0]
    clusterCount=zeros(1,num);  %各聚类有的帧数   [0,0,0,0,0,0,0,0,0,0,0,0,....0,0,0,0]
    count=0;        %聚类的个数    
     
    %threshold=0.75;  %阈值越大帧越多
    %airplane这个视频阈值设为0.93比较合适   0.95更好
    %********************************************************阈值**************************************************************%
    threshold=0.91;  %阈值
    centrodR=zeros(num,256);   %聚类质心R的直方图   第一帧图片256个初始化全部为0,第二帧也是,其余帧都是  %%%后面相似度大加入一帧后会对其进行调整
    centrodG=zeros(num,256);   %聚类质心G的直方图
    centrodB=zeros(num,256);   %聚类质心B的直方图
     
    if num==0
        error('Sorry, there is no pictures in images folder!');
    else
        %令首帧形成第一个聚类
        img=imread(strcat('images/',filenames(1).name));
        count=count+1;    %产生第一个聚类
        [preCountR,x]=imhist(img(:,:,1));   %red histogram    得到红色的直方图一共256个数值,每个数值有多少作为直方图的高度
        [preCountG,x]=imhist(img(:,:,2));   %green histogram
        [preCountB,x]=imhist(img(:,:,3));   %blue histogram
        
        cluster(1)=1;   %设定第一个聚类选取的关键帧初始为首帧  cluster变为了(1,0,0,0,0,......,0,0,0)cluster(1)是改变了第一个元素
        clusterCount(1)=clusterCount(1)+1;%clusterCount(1)为0,加1,变为1,最终 clusterCount(1)为[1,0,0,0,.....,0,0,0]
        centrodR(1,:)=preCountR; % centrodR本来是num(帧个数)行,256列,全部为0.。现在第一行为第一帧的红色直方图各个数值的高度
        centrodG(1,:)=preCountG;
        centrodB(1,:)=preCountB;
       
        visit = 1;
        for k=2:num
            img=imread(strcat('images/',filenames(k).name));  %循环读取每一帧,首先是第2帧
            [tmpCountR,x]=imhist(img(:,:,1));   %red histogram  得到红色分量直方图  第二幅图片的红色直方图
            [tmpCountG,x]=imhist(img(:,:,2));   %green histogram
            [tmpCountB,x]=imhist(img(:,:,3));   %blue histogram
     
            clusterGroupId=1;  %新定义的一个变量clusterGroupId为1
            maxSimilar=0;   %新定义,相似度
        
           
            for clusterCountI= visit:count          %目前 count为1   定义新变量clusterCountI  I来确定这一帧归属于第一个聚类还是第二个聚类
                sR=0;
                sG=0;
                sB=0;
                %运用颜色直方图法的差别函数
                for j=1:256
                    sR=min(centrodR(clusterCountI,j),tmpCountR(j))+sR;%,j从1到256,第一帧中R的所有值256个亮度  以及第二帧的红色直方图所有高度值  进行比较选最小的
                    sG=min(centrodG(clusterCountI,j),tmpCountG(j))+sG;
                    sB=min(centrodB(clusterCountI,j),tmpCountB(j))+sB;
                end
                dR=sR/sum(tmpCountR);
                dG=sG/sum(tmpCountG);
                dB=sB/sum(tmpCountB);
                %YUV,persons are sensitive to Y
                d=0.30*dR+0.59*dG+0.11*dB;  %运用颜色直方图法的差别函数  定义了d  差别函数
                if d>maxSimilar
                    clusterGroupId=clusterCountI;
                    maxSimilar=d;
                end
            end
            
            if maxSimilar>threshold
                %相似度大,与该聚类质心距离小
                %加入该聚类,并调整质心
                for ii=1:256    
                    centrodR(clusterGroupId,ii)=centrodR(clusterGroupId,ii)*clusterCount(clusterGroupId)/(clusterCount(clusterGroupId)+1)+tmpCountR(ii)*1.0/(clusterCount(clusterGroupId)+1);
                    centrodG(clusterGroupId,ii)=centrodG(clusterGroupId,ii)*clusterCount(clusterGroupId)/(clusterCount(clusterGroupId)+1)+tmpCountG(ii)*1.0/(clusterCount(clusterGroupId)+1);
                    centrodB(clusterGroupId,ii)=centrodB(clusterGroupId,ii)*clusterCount(clusterGroupId)/(clusterCount(clusterGroupId)+1)+tmpCountB(ii)*1.0/(clusterCount(clusterGroupId)+1);
                end
                clusterCount(clusterGroupId)=clusterCount(clusterGroupId)+1;
                cluster(k)=clusterGroupId;   %第k帧在第clusterGroupId个聚类里面   cluster(3)等于1或者2,,也就是属于第一个聚类或者第二个聚类
            else
                %形成新的聚类,增加一个聚类质心
                count=count+1;
                 visit = visit+1;
                clusterCount(count)=clusterCount(count)+1;
                centrodR(count,:)=tmpCountR;
                centrodG(count,:)=tmpCountG;
                centrodB(count,:)=tmpCountB;
                cluster(k)=count;   %第k帧在第count个聚类里面   否则 cluster(k)就在新建的聚类中
            end
        end
        
        %至此,所有帧都划进相应的聚类,一共有count个聚类,第k帧在第cluster(k)聚类中
        %现欲取出每个聚类中离质心距离最近,即相似度最大的作为该聚类的关键帧
        maxSimilarity=zeros(1,count);
        frame=zeros(1,count);
        for i=1:num
            sR=0;
            sG=0;
            sB=0;
            %运用颜色直方图法的差别函数
            for j=1:256
                sR=min(centrodR(cluster(i),j),tmpCountR(j))+sR;%每一帧和聚类质心进行比较,取最小值 
                sG=min(centrodG(cluster(i),j),tmpCountG(j))+sG;
                sB=min(centrodB(cluster(i),j),tmpCountB(j))+sB;
            end
            dR=sR/sum(tmpCountR);
            dG=sG/sum(tmpCountG);
            dB=sB/sum(tmpCountB);
            %YUV,persons are sensitive to Y
            d=0.30*dR+0.59*dG+0.11*dB;
            if d>maxSimilarity(cluster(i))
                maxSimilarity(cluster(i))=d;
                frame(cluster(i))=i;
            end
        end
        
        for j=1:count
            key(frame(j))=1;
            figure(j);
            imshow(strcat('images/',filenames(frame(j)).name));
        end
    end
     
    keyFrameIndexes=find(key)
    

    这种方法在878帧图片中提取出198帧,冗余度还是比较高。

    (11) 使用CNN来保存图片在使用聚类法提取关键帧,这种方法由于TensorFlow环境搭配的有问题,没有实际运行,在这给出链接

    这个

    三、整理结果

    博主使用一分十五秒00000.MP4视频, 共1898帧,分为七类,帧差最大值帧间差法提取的效果很好。k-means聚类法效果不好,原因在于(1)代码是copy 别人的,没有进行优化,(2)博主对帧间聚类方法理论研究浅薄,指导不了实践。

    k-means聚类 提出484帧

    帧差最大值帧间差法提取出35帧

    参考资料:

    [1]苏筱涵.深度学习视角下视频关键帧提取与视频检索研究[J].网络安全技术与应用,2020(05):65-66.

    [2]王红霞,王磊,晏杉杉.视频检索中的关键帧提取方法研究[J].沈阳理工大学学报,2019,38(03):78-82.

    [3]王俊玲,卢新明.基于语义相关的视频关键帧提取算法[J/OL].计算机工程与应用:1-10[2020-11-04].http://kns.cnki.net/kcms/detail/11.2127.TP.20200319.1706.018.html.

    [4] 张晓宇,张云华.基于融合特征的视频关键帧提取方法.计算机系统应用,2019,28(11):176–181. http://www.c-s-a.org.cn/1003-3254/7163.html

    [5] [1]周舟,韩芳,王直杰.面向手语识别的视频关键帧提取和优化算法[J/OL].华东理工大学学报(自然科学版):1-8[2020-11-05].https://doi.org/10.14135/j.cnki.1006-3080.20191201002.

    附录:

    1、数字视音频处理知识点小结

    [2020-11-04].http://kns.cnki.net/kcms/detail/11.2127.TP.20200319.1706.018.html.

    [4] 张晓宇,张云华.基于融合特征的视频关键帧提取方法.计算机系统应用,2019,28(11):176–181. http://www.c-s-a.org.cn/1003-3254/7163.html

    [5] [1]周舟,韩芳,王直杰.面向手语识别的视频关键帧提取和优化算法[J/OL].华东理工大学学报(自然科学版):1-8[2020-11-05].https://doi.org/10.14135/j.cnki.1006-3080.20191201002.
    [6] https://me.csdn.net/cungudafa这位小姐姐的博客

    附录:

    1、数字视音频处理知识点小结

    展开全文
  • 视频关键帧提取常用方法

    千次阅读 2019-12-26 17:07:00
    基于镜头的关键帧提取算法视频检索领域中最先发展起来,也是目前最为成熟的一种通用方法,该算法的一般实现过程是:先按照某种技术手段把源视频文件按照镜头变化分割,然后在视频每个镜头中选择首、尾两帧作为关键...
  • 常见的关键帧提取算法有、基于镜头边界的方法、 基于图像内容的方法、基于聚类的提取方法、基于运动分析的方法、 基于压缩视频流的方法。以上这些方法均有各自的优缺点和一定的局限性,只适 合于特定的视频,不具有...
  • 一种视频关键帧提取方法【专利摘要】公开了一种视频关键帧的提取方法,属于视频数据处理领域。本发明中关键帧提取包含:计算视频帧灰度质心,并依据相邻帧间灰度质心距离,以及当前视频帧灰度质心与前序视觉相似帧...
  • 基于仿射传播聚类的视频关键帧提取方法.pdf
  • 基于人工免疫有序聚类的视频关键帧提取方法.pdf
  • 基于K均值聚类的视频关键帧提取技术研究.pdf
  • 为了有效、且自适应的提取视频中的关键帧,提出了一种改进的三维蚁堆新算法。该算法首先提取每一帧中H-S-V颜色空间的三维特征向量,并将其表示为H-S-V三维欧式空间中的点,之后通过改进的三维蚁堆算法,自适应的...
  • 针对压缩视频序列提出一种基于镜头的关键帧提取改进算法。其核心是根据压缩视频序列的编码特点,只需要对其进行部分解码,利用I帧信息的直流分量信息构造DC缩微图,并结合图像帧不同区域DC信息的重要程度差异进行...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 10,218
精华内容 4,087
关键字:

视频关键帧提取算法