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

树莓派4 8GB双USB摄像头OpenCV C++读取卡顿,JS正常

问题原因分析
  • USB总线带宽饱和:树莓派4的USB总线为共享带宽设计,两个Eternico ET101 HD摄像头若以未压缩格式(如YUYV)输出视频,单路720p/30fps的YUYV流带宽约207Mbps,两路总和会超出USB总线实际可用带宽(USB 2.0实际可用约300Mbps以内)。而浏览器JS默认调用摄像头的MJPEG压缩输出格式,带宽仅需几十Mbps,因此能正常运行。
  • OpenCV默认参数不合理:CAP_ANY自动选择的V4L2后端默认采用未压缩的YUYV格式读取,未启用摄像头的硬件压缩能力,进一步加剧带宽占用。
  • 同步读取阻塞:单线程下依次调用两个VideoCapture::read()会触发IO阻塞,带宽不足时摄像头硬件会停止输出,最终导致帧冻结。
C++解决方案

1. 启用MJPEG压缩+多线程读取

通过指定摄像头输出MJPEG压缩格式降低带宽占用,同时用多线程分别处理两个摄像头的读取,避免同步阻塞:

#include <opencv2/core.hpp>
#include <opencv2/videoio.hpp>
#include <opencv2/highgui.hpp>
#include <iostream>
#include <thread>
#include <unistd.h>

using namespace cv;
using namespace std;

void captureLoop(int deviceID, const string& winName) {
    VideoCapture cap;
    // 强制使用V4L2后端
    if (!cap.open(deviceID, CAP_V4L2)) {
        cerr << "Failed to open camera " << deviceID << "\n";
        return;
    }

    // 配置摄像头输出MJPEG格式、分辨率、帧率
    cap.set(CAP_PROP_FOURCC, VideoWriter::fourcc('M', 'J', 'P', 'G'));
    cap.set(CAP_PROP_FRAME_WIDTH, 1280);
    cap.set(CAP_PROP_FRAME_HEIGHT, 720);
    cap.set(CAP_PROP_FPS, 30);

    // 验证参数是否生效
    cout << "Camera " << deviceID << " actual params: "
         << cap.get(CAP_PROP_FRAME_WIDTH) << "x" << cap.get(CAP_PROP_FRAME_HEIGHT)
         << ", FPS: " << cap.get(CAP_PROP_FPS) << "\n";

    Mat frame;
    while (true) {
        if (!cap.read(frame)) {
            cerr << "Blank frame from camera " << deviceID << "\n";
            break;
        }
        imshow(winName, frame);
        // 每个线程需单独处理waitKey,避免窗口无响应
        if (waitKey(1) >= 0) {
            destroyAllWindows();
            exit(0);
        }
    }
}

int main() {
    // 启动两个独立线程分别读取摄像头
    thread cam0(captureLoop, 0, "Camera 0");
    thread cam1(captureLoop, 1, "Camera 1");

    cam0.join();
    cam1.join();
    return 0;
}

2. 网络推流实现(RTSP为例)

结合OpenCV+FFmpeg实现RTSP推流,需确保树莓派已安装FFmpeg开发库:

#include <opencv2/core.hpp>
#include <opencv2/videoio.hpp>
#include <opencv2/highgui.hpp>
#include <iostream>
#include <thread>

using namespace cv;
using namespace std;

void streamLoop(int deviceID, const string& winName, const string& rtspUrl) {
    VideoCapture cap;
    if (!cap.open(deviceID, CAP_V4L2)) {
        cerr << "Failed to open camera " << deviceID << "\n";
        return;
    }

    cap.set(CAP_PROP_FOURCC, VideoWriter::fourcc('M', 'J', 'P', 'G'));
    cap.set(CAP_PROP_FRAME_WIDTH, 1280);
    cap.set(CAP_PROP_FRAME_HEIGHT, 720);
    cap.set(CAP_PROP_FPS, 30);

    int width = cap.get(CAP_PROP_FRAME_WIDTH);
    int height = cap.get(CAP_PROP_FRAME_HEIGHT);
    double fps = cap.get(CAP_PROP_FPS);

    // 初始化RTSP推流(需提前部署RTSP服务器如EasyDarwin)
    VideoWriter writer;
    if (!writer.open(rtspUrl, 
                     CAP_FFMPEG, 
                     VideoWriter::fourcc('H', '2', '6', '4'), 
                     fps, 
                     Size(width, height), 
                     true)) {
        cerr << "Failed to open RTSP stream for camera " << deviceID << "\n";
        return;
    }

    Mat frame;
    while (true) {
        if (!cap.read(frame)) {
            cerr << "Blank frame from camera " << deviceID << "\n";
            break;
        }
        imshow(winName, frame);
        writer.write(frame); // 推送帧到RTSP服务器
        if (waitKey(1) >= 0) {
            destroyAllWindows();
            exit(0);
        }
    }
}

int main() {
    // 替换为你的RTSP服务器地址
    thread cam0(streamLoop, 0, "Camera 0", "rtsp://your-server:554/stream0");
    thread cam1(streamLoop, 1, "Camera 1", "rtsp://your-server:554/stream1");

    cam0.join();
    cam1.join();
    return 0;
}

3. 额外优化建议

  • 分离USB端口:将两个摄像头分别插入USB 3.0和USB 2.0端口,避免单总线带宽竞争。
  • 降低分辨率/帧率:若MJPEG仍出现带宽问题,可将分辨率降至640x480或帧率降至15fps。
  • 预配置摄像头:运行程序前用v4l2-ctl工具锁定参数:
    v4l2-ctl --device=/dev/video0 --set-fmt-video=width=1280,height=720,pixelformat=MJPG
    v4l2-ctl --device=/dev/video1 --set-fmt-video=width=1280,height=720,pixelformat=MJPG
    

内容的提问来源于stack exchange,提问作者Andrej Vyšný

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.05 12:26:12