You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

树莓派4 64位系统无法稳定同时访问两个USB摄像头问题咨询

树莓派64位系统双USB摄像头多进程稳定调用方案

问题背景

  • 运行环境:64位版本树莓派4操作系统
  • 开发场景:实现目标检测、人脸识别两个功能模块,分别调用索引为0、2的USB摄像头,采用multiprocessing多进程模式并行运行
  • 故障表现:双摄像头无法稳定同步工作,频繁随机出现单摄像头正常运行、另一摄像头返回can't open camera by index报错的问题。编写简化测试代码验证时故障可稳定复现,双摄像头启动成功概率随机,经常仅能识别到其中一个。

测试代码如下:

import time

cam1 = cv2.VideoCapture(0)
cam2 = cv2.VideoCapture(2)
time.sleep(2.0)
while True:
    ret1, frame1 = cam1.read()
    ret2, frame2 = cam2.read()


    if ret1:
        frame1 = cv2.cvtColor(frame1, cv2.COLOR_BGR2GRAY)
        cv2.imshow('cam1', frame1)

    if ret2:
        frame2 = cv2.cvtColor(frame2, cv2.COLOR_BGR2GRAY)
        cv2.imshow('cam2', frame2)

    if cv2.waitKey(1) & 0xFF == ord('s'):
        break

cam1.release()
cam2.release()
cv2.destroyAllWindows()

已完成排查

  • 尝试初始化摄像头时显式指定V4L后端,问题未解决,对应代码:
cap = cv2.VideoCapture(index, cv2.CAP_V4L)
  • 硬件兼容性校验通过,lsusb可正常识别两个摄像头设备,返回结果:
pi@raspberrypi:~ $ lsusb
    Bus 002 Device 001: ID 1d6b:0003 Linux Foundation 3.0 root hub
    Bus 001 Device 005: ID 10c4:8108 Silicon Labs USB OPTICAL MOUSE
    Bus 001 Device 004: ID 2a7a:9a18 CASUE CASUE USB Keyboard
    Bus 001 Device 007: ID 0ac8:0345 Z-Star Microelectronics Corp. USB 2.0 PC Camera
    Bus 001 Device 008: ID 0c45:6366 Microdia Webcam Vitade AF
    Bus 001 Device 002: ID 2109:3431 VIA Labs, Inc. Hub
    Bus 001 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub
  • /dev目录下两个摄像头的设备节点均正常生成。

可落地稳定解决方案

  • 放弃数字索引初始化方式,绑定固定设备路径。数字索引随系统设备枚举顺序动态变化,极易出现索引抢占问题。先执行v4l2-ctl --list-devices查询两个摄像头对应的设备路径,再配置udev规则将两个摄像头绑定为固定别名(如/dev/cam_detect对应目标检测摄像头、/dev/cam_face对应人脸识别摄像头),初始化时直接传入固定路径而非数字索引:
cam_detect = cv2.VideoCapture("/dev/cam_detect", cv2.CAP_V4L)
cam_face = cv2.VideoCapture("/dev/cam_face", cv2.CAP_V4L)
  • 主动降低摄像头带宽占用。树莓派4的USB接口为共享带宽设计,双摄像头默认以最高分辨率、最高帧率启动时会出现带宽抢占,导致随机枚举失败。摄像头初始化完成后立刻设置合理的分辨率与帧率,双路同时运行时建议单路参数不超过640*480@15fps,设置完成后预留2秒硬件初始化时间再开始读帧:
cam_detect.set(cv2.CAP_PROP_FRAME_WIDTH, 640)
cam_detect.set(cv2.CAP_PROP_FRAME_HEIGHT, 480)
cam_detect.set(cv2.CAP_PROP_FPS, 15)
time.sleep(2)

如果调整参数后仍存在带宽不足问题,将两个摄像头分别插在树莓派不同的USB控制器接口上,不要共用同一个USB Hub扩展接口。

  • 多进程场景下禁止跨进程传递VideoCapture对象。multiprocessing默认采用fork模式创建子进程,主进程中初始化的摄像头句柄无法被子进程正常继承,会出现资源抢占。必须在每个子进程的启动逻辑内部独立初始化对应摄像头,不要在主进程提前创建摄像头对象再传入子进程。
  • 增加初始化重试逻辑。USB摄像头硬件初始化存在不确定的时间差,单次打开失败属于正常现象,实现带重试的初始化逻辑,单次失败后释放资源间隔1秒重试,最多重试5次:
import cv2
import time

def init_camera(dev_path, width=640, height=480, fps=15, retry=5):
    cam = None
    for attempt in range(retry):
        cam = cv2.VideoCapture(dev_path, cv2.CAP_V4L)
        if cam.isOpened():
            cam.set(cv2.CAP_PROP_FRAME_WIDTH, width)
            cam.set(cv2.CAP_PROP_FRAME_HEIGHT, height)
            cam.set(cv2.CAP_PROP_FPS, fps)
            ret, _ = cam.read()
            if ret:
                return cam
        if cam:
            cam.release()
        time.sleep(1)
    raise RuntimeError(f"摄像头 {dev_path} 初始化失败")
  • 强制V4L2采用用户指针IO模式。OpenCV默认使用MMAP方式读取V4L2设备帧,在部分廉价USB摄像头上会出现资源冲突,在导入cv2前设置环境变量关闭MMAP模式即可:
import os
os.environ["OPENCV_VIDEOIO_PRIORITY_V4L2"] = "1"
os.environ["OPENCV_VIDEOIO_V4L2_USE_MMAP"] = "0"
# 环境变量设置完成后再导入cv2
import cv2

内容的提问来源于stack exchange,提问作者Ahmed saad

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.02 01:48:34