视频关键帧抽取终结篇——关键帧是什么?

在之前的博文中都抛出了问题,而没有解决,这里做最后的解决!!!

视频关键帧分为I帧,P帧,B帧,这里介绍下区别,也是我搜索得到的,仅供参考。

I帧才是关键帧,P,B算不上关键帧。

I帧是帧内压缩编码得到的,通常是每个GOP组的第一帧/基础帧,在一组中只有一个I帧,I帧所占信息量大,解码时仅有I帧即可完整重构图像,所以才叫关键帧。

P帧与B帧是帧间压缩,P帧没有完整图像数据,只有与前一帧的差别信息,因此也叫预测帧,B帧则是考虑前后帧的差别(故而也叫双向预测帧),因此B帧解码时间最长,压缩比最大。

参考上面博文,又找到了一个方法,感谢帮助我的大佬。cv2解码,当然其他解码也可,我看看是否结果一样。

我看了下,这个方法是找到关键帧的index,然后再次读视频(耗时问题也算差强人意吧),我在上面博文中也提及了。

下面是用ffprobe得到的帧:以baby.mp4为例

'pict_type=I\r\npict_type=P\r\npict_type=P\r\npict_type=B\r\npict_type=P\r\npict_type=B\r\npict_type=P\r\npict_type=B\r\npict_type=P\r\npict_type=B\r\npict_type=P\r\npict_type=B\r\npict_type=P\r\npict_type=B\r\npict_type=P\r\npict_type=B\r\npict_type=P\r\npict_type=B\r\npict_type=P\r\npict_type=B\r\npict_type=P\r\npict_type=B\r\npict_type=P\r\npict_type=B\r\npict_type=P\r\npict_type=B\r\npict_type=P\r\npict_type=B\r\npict_type=P\r\npict_type=B\r\npict_type=P\r\npict_type=B\r\npict_type=P\r\npict_type=B\r\npict_type=P\r\npict_type=B\r\npict_type=P\r\npict_type=B\r\npict_type=P\r\npict_type=B\r\npict_type=P\r\npict_type=B\r\npict_type=P\r\npict_type=B\r\npict_type=P\r\npict_type=B\r\npict_type=P\r\npict_type=B\r\npict_type=P\r\npict_type=B\r\npict_type=P\r\npict_type=B\r\npict_type=P\r\npict_type=B\r\npict_type=P\r\npict_type=B\r\npict_type=P\r\npict_type=B\r\npict_type=P\r\npict_type=B\r\npict_type=P\r\npict_type=B\r\npict_type=P\r\npict_type=B\r\npict_type=P\r\npict_type=B\r\npict_type=P\r\npict_type=B\r\npict_type=P\r\npict_type=B\r\npict_type=P\r\npict_type=B\r\npict_type=P\r\npict_type=B\r\npict_type=P\r\npict_type=B\r\npict_type=P\r\npict_type=B\r\npict_type=P\r\npict_type=B\r\npict_type=P\r\npict_type=B\r\npict_type=P\r\npict_type=B\r\npict_type=P\r\npict_type=B\r\npict_type=P\r\npict_type=B\r\npict_type=P\r\npict_type=P\r\npict_type=I\r\npict_type=B\r\npict_type=P\r\npict_type=B\r\npict_type=P\r\npict_type=B\r\npict_type=P\r\npict_type=B\r\npict_type=P\r\npict_type=B\r\npict_type=P\r\npict_type=B\r\npict_type=P\r\npict_type=B\r\npict_type=P\r\npict_type=B\r\npict_type=P\r\npict_type=B\r\npict_type=P\r\npict_type=B\r\npict_type=P\r\npict_type=B\r\npict_type=P\r\npict_type=P\r\npict_type=P\r\npict_type=P\r\npict_type=P\r\npict_type=P\r\npict_type=P\r\npict_type=P\r\npict_type=P\r\npict_type=P\r\npict_type=P\r\npict_type=P\r\npict_type=P\r\npict_type=P\r\npict_type=P\r\npict_type=P\r\npict_type=B\r\npict_type=P\r\npict_type=B\r\npict_type=P\r\npict_type=B\r\npict_type=P\r\npict_type=B\r\npict_type=P\r\npict_type=B\r\npict_type=P\r\npict_type=B\r\npict_type=P\r\npict_type=B\r\npict_type=P\r\n'

可见,I,P,B帧都有。这样就得到了index。

cv2中获取指定index的帧,与cv2.CAP_PROP_POS_FRAMES有关,后来得到cv2保存的图片比直接用ffmpeg的内存大,图像是一样的。可以认为无差别吧。我试试另一个解码器,看看耗时上有没有差别,仍旧以baby.mp4(1.1M)和baby2.mp4(1.4M),较大的视频vLaugh199.mp4 (19M)为例。

比较方法是只读取数据,鉴于图像解码可能有差别,恢复的图像大小不一样,所以第一步,先保存为图,如果图像一样的话,那么只看读取数据的时间。

中间遇到一个问题,让我蒙蔽了,cv2指定的某个index得到的frame为空,这就尴尬了。

因为下面的ret为False,其实这就说明cv2的解码与ffmpeg是不一样的,加个判断,避免报错。

ret, frame = cap.read()

cv2解码得到的关键帧只有15个,而ffmpeg有16个,尽管后者得到图有些小,质量可能不清晰。

整体上相差不大,可以忽略这个15还是16的问题吧。

其中又遇到了一个问题,另一个解码器得到的图到底是什么格式?RGB or BGR ?我直接用imwrite保存得到的图反而没有错??

鉴于此,又新开一个博文。等待官方答复中。。

下面进入正文:测试解码时间,其实我绝对就是看PyDecoder的耗时,因为这个我之前测试过,的确比较快一点。

【PyDecoder采用GPU时可能会出现问题,卡死,我有点蒙蔽】

time: 24.900450 PyDecoder

time: 4.887592   cv2  可见有index时抽帧还是cv2快

中间又遇到一个问题,用time.clock()计算时间得到的结果不对(可能是版本问题,有提示升级了,反正啥幺蛾子都有,奇怪的问题不纠结,能避免就好),于是换成了time.time()

DeprecationWarning: time.clock has been deprecated in Python 3.3 and will be removed from Python 3.8: use time.perf_counter or time.process_time instead
  start=time.clock()



>>> start=time.clock()
>>> end=time.clock()
>>> end-start

#服务器上这种计算方法出现问题

另外有相关问题可以加入QQ群讨论,不设微信群

QQ群:868373192 

语音图像视频深度-学习群

发布了228 篇原创文章 · 获赞 216 · 访问量 6万+

猜你喜欢

转载自blog.csdn.net/SPESEG/article/details/104920069
今日推荐