前言:
目前朋友们对“mp算法代码”都比较重视,各位老铁们都想要学习一些“mp算法代码”的相关知识。那么小编也在网络上汇集了一些关于“mp算法代码””的相关文章,希望看官们能喜欢,你们一起来了解一下吧!抽帧
一个高帧率的视频流,AI准备处理的过程中,并不一定每个帧都需要进行处理。
例如大部分视频是25FPS,对应每张图的间隔大概是40ms,如果要做行人检测,那肯定不需要每个帧都检测,在视频画面内,人的移动速度有限,为了节省计算资源,我们可能进行抽帧处理。
比方只需要3FPS的图像处理即可,计算一下大概平均图,检测一次即可。
视频读取
视频和图像处理比较流行的组件就是opencv,使用opencv来读取视频实现也是比较简单。
我们使用unittest框架来写一个性能测试的TestCase,每个用例自动初始化视频读取的cap,用例执行完毕销毁。使用到setUp和tearDown方法,在每个test执行开始之前和结束之后会自动调用。
如下,setUp中初始化cap,用原视频帧率和我们期望检测的帧率做一个计算得到skip,方便处理向下取整。
def setUp(self) -> None: self.cap = cv2.VideoCapture(filename=self.mp, apiPreference=cv2.CAP_ANY) # 获取帧率 self.fps = self.cap.get(cv2.CAP_PROP_FPS) self.cap.set(cv2.CAP_PROP_MODE, 0) self.frame_count = self.cap.get(cv2.CAP_PROP_FRAME_COUNT) # 输出帧率 self.out_rate = 3 logging.warning(f"fps:{self.fps}") self.ext = ".jpg" self.skip = int(self.fps//self.out_rate) self.cur_frame = 0
用例执行完毕销毁cap
def tearDown(self) -> None: self.cap.release()
定位帧来实现抽帧处理(不太好的方式)
抽帧比较很有意思了, 我们想到了数组下标,对于这些帧,我们设定读取的帧的位置是不是就很简单,cv2对于视频cap确实有一个这个属性设置cv2.CAP_PROP_POS_MSEC。
关键代码如下,我们通过设置当前帧self.cur_frame,但不是连续的,而是按照skip跳转的,这样就很方便能够达到我们效果。
while ret: self.cap.set(cv2.CAP_PROP_POS_MSEC, self.cur_frame) ret, frame = self.cap.read() self.cur_frame += self.skip count += self.skip handle_count += 1 if not ret: logging.error("数据获取完成") break
看下生成的图片,我们将帧号写入文件名称中,间隔刚好8倍数的帧正常输出
略过非关键帧方式(推荐)
我们是不是非要想着直接去取我们想要的帧? 因为这种方式性能慢。这就是比较神奇的地方,我开始也以为采用定位帧,设置cv2.CAP_PROP_POS_MSEC的方式,就像数组的下标,性能应该很快呀,经过实测,这个索引越大,几万几十万的时候,性能会下降,而且这个速度也不一定是最快的。
格局打开,如果能够略过我们不想要的帧,遇到我们想识别的帧再去解码,是不是就达到我们目的了呢?那我们期望cv2有两种功能的函数,一种是只遍历,不解码数据;一种是遍历要解码数据。
认真翻了一下opencv的官网,还真找到了。 grab()就是仅仅遍历的目的,它通过retrieve()去获取数据,而且这个retrieve()可以设置参数是否解码,方法如下,这个我也很无聊的测试了下,这样读取数据,每秒钟能读几千帧,基本就是IO,本文我就不展开了。
self.cap.set(cv2.CAP_PROP_FORMAT, -1)
那我们换个策略,每个skip个帧,read一下,其他帧都进行grab处理,这样就能达到我们的效果了。代码如下
while ret: if self.cur_frame % self.skip == 0: # print(f"输出:{slice_sn}") ret, frame = self.cap.read() else: ret = self.cap.grab() frame = None self.cur_frame += 1 if not ret: logging.error("数据获取完成") break
定位和跳过的性能比较
两种方式我们都实现了,我用自己的MAC来测试了一下,加上一些统计打印,看看性能测试如何呢。
定位帧的方式,每秒大概20+帧
采用grab跳过方式,每秒大概47+帧左右,非常稳定。
从结果也可以看出,grab方式速度还是快了很多。那抽帧用grab方式更合适。
另外为了加速,还可以采用GPU解码,本文就不展开了。
标签: #mp算法代码