Python多线程——视频转存图片的加速实现

  视频转存图片的代码实现如下,record_time为用于计时的装饰器,详见此文;video2pics为视频转存图片函数,读取视频的每一帧保存为jpg文件

import cv2
import time
import os

def record_time(func):

    def wrapper(*args, **kwargs):
        start = time.time()
        result = func(*args, **kwargs)
        end = time.time()
        print(f'{func.__name__}执行时间:{end-start:.3f}秒')
        return result

    return wrapper

@record_time
def video2pics(video_path, save_dir_path):
    pics = cv2.VideoCapture(video_path)
    c = 0
    while pics.isOpened():
        rval, frame = pics.read()
        if rval:
            save_path = os.path.join(save_dir_path, str(c)+'.jpg')
            cv2.imwrite(save_path, frame)
            c += 1
        else:
            break
    pics.release()
 
 if __name__ == '__main__':
    video_path = r'D://Video/raw.mp4'
    save_dir_path = r'D://pics'
    video2pics(video_path,save_dir_path)

将一个1080p,帧率为25,时长5分钟的视频转存为7500张图片,此程序需花费433秒
原运行时长
  在上个程序中,存储这么多图片,可能造成程序耗时长的一部分原因,而存图片是一个I/O输入/输出任务,因此考虑使用多线程。在操作系统中,进程是分配内存的基本单位,一个程序包含一个或多个进程,而线程是分配CPU的基本单位,一个进程通常有一个或多个线程,多个线程共享内存,针对密集的I/O操作,创建多个线程并发实现减少运行时间。

from concurrent.futures import ThreadPoolExecutor

def video2pics(video_path, save_dir_path, thread_nums=25):
    pics = cv2.VideoCapture(video_path)
    c = 0
    with ThreadPoolExecutor(max_workers=thread_nums) as pool:
        while pics.isOpened():
            rval, frame = pics.read()
            if rval:
                save_path = os.path.join(save_dir_path, str(c)+'.jpg')
                pool.submit(cv2.imwrite, save_path, frame)
                c += 1
            else:
                break
    pics.release()

新的video2pics创建了一个线程池,为cv2.imwrite方法创建线程。使用线程池的原因是因为如果每一个图片下载任务都使用一个线程的话线程创建、调度和释放会有较大开销,所以使用容器提前创建好若干线程,使用线程时从其中拿出一个线程,用完后不释放线程,而是放回线程池,重复利用。可以看到,使用25个线程,运行时长明显减少,多线程加速了视频转存图片的实现。新运行时长
  视频可以转存为图片,图片也可以合成视频,可自行设置需要的编码格式,帧率,分辨率。该过程暂时没想到如何使用多线程,之后如果解决再补上。

def pics2video(pics_dir_path, video_save_path, fps=25, size=(1920, 1080), pic_nums = 7500):
    fourcc = cv2.VideoWriter_fourcc(*'I420')
    out = cv2.VideoWriter(video_save_path, fourcc, fps, size)
    for c in range(pic_nums):
        pic_path = os.path.join(pics_dir_path, str(c)+'.jpg')
        frame = cv2.imread(pic_path)
        out.write(frame)
    out.release()
    
 if __name__ == '__main__':
 	save_dir_path = r'E://pics'
    video_save_path = r'E://Video/new.avi'
    pics2video(save_dir_path,video_save_path)
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值