Python OpenCV多USB摄像头快速开启及并发采集优化方案咨询
问题1:加快OpenCV打开USB摄像头的速度的方案
- 跳过不必要的属性协商:你现有代码是初始化完成后再设置分辨率,可改为在
VideoCapture初始化阶段就传入参数减少后续驱动协商耗时。另外DSHOW后端默认会加载冗余的驱动兼容层,你可以在设备管理器中禁用无关的摄像头驱动项,同时初始化后直接关闭自动曝光、自动白平衡等默认自动配置,不要等摄像头自主协商参数,单台初始化可省1-2秒。 - 简化有效帧判断逻辑:现有代码用
while循环反复判断帧是否有效,实际上USB摄像头初始化后前2-3帧通常是缓存的黑帧,直接固定丢弃前2帧再取图即可,省去反复判断的耗时,也能避免空帧报错。 - 编译轻量化OpenCV:官方预编译的OpenCV内置了很多不需要的采集后端、冗余组件,自行编译时只勾选
CAP_DSHOW后端、移除其他不需要的组件,初始化速度可提升30%左右。
问题2:多摄像头并发初始化及采集实现方案
- 可通过多进程实现并发,不要用多线程:Python的GIL锁会导致多线程下IO密集型操作也存在阻塞,用
multiprocessing库给每个摄像头分配独立进程做初始化+采集,20台摄像头的总耗时基本和单台耗时持平,不会串行累加。 - 提前规避USB带宽瓶颈:20台1080P USB摄像头如果接在同一个USB控制器下会出现带宽不足,需要把摄像头分散接到主板不同的USB Hub上,建议每个USB控制器下接入的1080P摄像头不超过4个,避免并发时出现初始化失败、掉帧问题。
- 单独捕获单进程异常:每个摄像头的采集进程单独做异常捕获,单台初始化失败不会影响其他摄像头的采集流程。
优化后代码示例
import cv2 import multiprocessing # 优化后的单摄像头采集函数 def take_picture(camera_id, pos, cursor): # 初始化时加入超时参数减少无效等待 cap = cv2.VideoCapture(camera_id, cv2.CAP_DSHOW, params=[cv2.CAP_PROP_READ_TIMEOUT, 1000]) # 提前设置分辨率减少协商时间 cap.set(cv2.CAP_PROP_FRAME_WIDTH, 1920) cap.set(cv2.CAP_PROP_FRAME_HEIGHT, 1080) # 关闭自动配置加快初始化速度,有需求可自行调整参数 cap.set(cv2.CAP_PROP_AUTO_EXPOSURE, 0) res = None name = None if cap.isOpened(): # 直接丢弃前2帧缓存,无需循环判断 for _ in range(2): cap.read() ret, frame = cap.read() if ret and frame is not None: real_location = f'station{pos}' name = f'{real_location}-collection{cursor}.png' res = frame cap.release() return (camera_id, name, res) # 多进程并发调用示例 if __name__ == '__main__': # 按实际需求补全所有摄像头的(ID、对应工位pos、采集批次cursor)参数 camera_params = [ (0, 1, 1), (1, 2, 1), # 剩余18台摄像头参数在此补全 ] # 进程池大小可根据CPU核心数调整,20台摄像头直接设20也可 with multiprocessing.Pool(processes=20) as pool: results = pool.starmap(take_picture, camera_params) # 处理采集结果 for camera_id, name, frame in results: if frame is not None: cv2.imwrite(name, frame) else: print(f"摄像头{camera_id}采集失败")
内容的提问来源于stack exchange,提问作者Xuanyuan Zhang
相关产品推荐
相关产品推荐

