优化OpenCV视频的读取速度

博客介绍了如何使用OpenCV优化视频处理速度。通过理解`grab()`和`retrieve()`函数的区别,实现按固定频率抽帧以减少计算资源浪费。此外,提出使用多线程技术并行处理视频帧,进一步提升处理效率。这种方法尤其适用于处理大型视频文件。

我们使用Opencv读取视频时,常规的做法是使用read()函数逐帧读取,如

import cv2

cap = cv2.VideoCapture("./test.mp4")
while True:
    # read a frame
    ret, frame = cap.read()
    if not ret:
        break
    # do something else
    ...
cap.release()

但是在图像处理时,并不需要逐帧处理,而是抽样的方式,这种情况下每一帧都读取会造成计算资源的浪费。查看Opencv的文档,会发现有这么几个函数介绍

virtual bool read (OutputArray image)
 Grabs, decodes and returns the next video frame. More...

virtual bool grab ()
 Grabs the next frame from video file or capturing device. More...
 
virtual bool retrieve (OutputArray image, int flag=0)
 Decodes and returns the grabbed video frame. More...

可以看出,read函数其实是grab和retireve函数的组合,grap是跳转到下一帧的位置,而retrieve是做具体的解码工作。显而易见,单纯的跳转要比解码快的多,所以我们不妨修改以下代码,假如抽样频率是5

import cv2

cap = cv2.VideoCapture("./test.mp4")
idx = 0
freq = 5
While True:
    idx += 1
    ret = cap.grab()
    if not ret:
         break
        
    if idx % freq == 1:
         continue
    
         ret, frame = cap.retrieve()
         if frame is None:    # exist broken frame
             break
         # do something else
         ...
cap.release()

读取速度会变成之前的1/5。

virtual bool read (OutputArray image)
 Grabs, decodes and returns the next video frame. More...

virtual bool grab ()
 Grabs the next frame from video file or capturing device. More...
 
virtual bool retrieve (OutputArray image, int flag=0)
 Decodes and returns the grabbed video frame. More...

但是对于超大的视频,这样单线程的读取方式还是不够快,因此可以考虑多线程同时读取,以加速处理速度

def process_video(self, start_frame, length):
    cap = cv2.VideoCapture("./test.mp4")
    cap.set(cv2.CAP_PROP_POS_FRAMES, start_frame)
    freq = 5
    for idx in range(length):
        ret = cap.grab()
        if not ret:
            break
        
        if idx % freq == 0:
            continue
    
        ret, frame = cap.retrieve()
        if frame is None:    # exist broken frame
            break
        # do something else
        ...
    cap.release()

在通过

frames_num = int(cap.get(cv2.CAP_PROP_FRAME_COUNT))

获取视频的总帧数,就可以平均分N个线程来处理视频了。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值