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

树莓派4B+OV9281相机:OpenCV isOpened为True但无法读取帧

树莓派Bullseye系统下OV9281单色相机无法被OpenCV读取的问题排查与修复

问题背景

使用树莓派4B(搭载最新Bullseye系统)搭配Waveshare OV9281-110全局快门单色相机时,通过libcamera-still -o test.png可正常捕获图像,但OpenCV调用VideoCapture时出现异常:isOpened()返回True,但grab()返回False,read()返回(False, None)。此前使用树莓派相机1.3时可正常读取。

用户测试代码:

import cv2
cam_port = 0
cam = cv2.VideoCapture(cam_port)
print(cv2.__version__)
print(cam.isOpened())
print(cam.grab())
print(cam.read())
cam.release()

输出:

4.5.5
True
False
(False, None)

相机设备信息(v4l2-ctl --device /dev/video0 --all):

Driver Info:
    Driver name      : unicam
    Card type        : unicam
    Bus info         : platform:fe801000.csi
    Driver version   : 5.15.56
    Capabilities     : 0xa5a00001
        Video Capture
        Metadata Capture
        Read/Write
        Streaming
        Extended Pix Format
        Device Capabilities
    Device Caps      : 0x25200001
        Video Capture
        Read/Write
        Streaming
        Extended Pix Format
Media Driver Info:
    Driver name      : unicam
    Model            : unicam
    Serial           : 
    Bus info         : platform:fe801000.csi
    Media version    : 5.15.56
    Hardware revision: 0x00000000 (0)
    Driver version   : 5.15.56
Interface Info:
    ID               : 0x03000005
    Type             : V4L Video
Entity Info:
    ID               : 0x00000003 (3)
    Name             : unicam-image
    Function         : V4L2 I/O
    Flags         : default
    Pad 0x01000004   : 0: Sink
      Link 0x02000007: from remote pad 0x1000002 of entity 'ov9281 10-0060': Data, Enabled, Immutable
Priority: 2
Video input : 0 (unicam-image: ok)
Format Video Capture:
    Width/Height      : 640/480
    Pixel Format      : 'BGR3' (24-bit BGR 8-8-8)
    Field             : None
    Bytes per Line    : 1920
    Size Image        : 921600
    Colorspace        : sRGB
    Transfer Function : sRGB
    YCbCr/HSV Encoding: ITU-R 601
    Quantization      : Full Range
    Flags  

核心原因分析

Bullseye系统默认采用libcamera相机栈替代传统v4l2直接访问,而OV9281作为单色全局快门相机,其像素格式兼容性、OpenCV对libcamera的支持程度是主要问题点。

排查与修复方案

方案1:手动指定相机像素格式

从设备信息看,当前相机输出格式为BGR3(24位彩色),但OV9281是单色相机,可尝试强制设置灰度格式或兼容的压缩格式:

修改测试代码:

import cv2
cam = cv2.VideoCapture(0)
# 设置分辨率
cam.set(cv2.CAP_PROP_FRAME_WIDTH, 640)
cam.set(cv2.CAP_PROP_FRAME_HEIGHT, 480)
# 尝试设置单色灰度格式Y800
cam.set(cv2.CAP_PROP_FOURCC, cv2.VideoWriter.fourcc('Y','8','0','0'))
# 如果Y800失败,尝试MJPG压缩格式
# cam.set(cv2.CAP_PROP_FOURCC, cv2.VideoWriter.fourcc('M','J','P','G'))

print(cv2.__version__)
print(cam.isOpened())
ret_grab = cam.grab()
print(ret_grab)
ret_read, frame = cam.read()
print(ret_read, frame is not None)

if ret_read:
    cv2.imwrite("test_opencv.png", frame)

cam.release()

方案2:使用v4l2loopback虚拟设备中转流

通过libcamera将相机流推送到虚拟v4l2设备,让OpenCV读取该虚拟设备:

  1. 安装依赖工具:
sudo apt update && sudo apt install v4l2loopback-dkms v4l2loopback-utils
  1. 加载虚拟设备模块:
sudo modprobe v4l2loopback video_nr=1 card_label="VirtualCam"
  1. 启动libcamera流并推送到虚拟设备:
libcamera-vid -t 0 --width 640 --height 480 --codec yuv420 -o - | v4l2loopback-ctl set-pixelformat /dev/video1 YU12
  1. 修改OpenCV代码读取虚拟设备:
import cv2
# 读取虚拟设备/dev/video1
cam = cv2.VideoCapture(1)
print(cv2.__version__)
print(cam.isOpened())
ret, frame = cam.read()
print(ret, frame is not None)

if ret:
    cv2.imwrite("test_virtual.png", frame)

cam.release()

方案3:重新编译支持libcamera的OpenCV

如果上述方案无效,需重新编译OpenCV并启用libcamera支持:

  1. 安装编译依赖:
sudo apt update && sudo apt install build-essential cmake git libgtk2.0-dev pkg-config libavcodec-dev libavformat-dev libswscale-dev libcamera-dev libcamera-apps-lite
  1. 克隆OpenCV及扩展模块:
git clone https://github.com/opencv/opencv.git
git clone https://github.com/opencv/opencv_contrib.git
  1. 编译安装:
cd opencv && mkdir build && cd build
cmake -D CMAKE_BUILD_TYPE=RELEASE -D CMAKE_INSTALL_PREFIX=/usr/local -D WITH_LIBCAMERA=ON -D OPENCV_EXTRA_MODULES_PATH=../../opencv_contrib/modules ..
make -j4  # 树莓派4B使用4线程编译
sudo make install
  1. 使用libcamera后端测试:
import cv2
# 直接指定libcamera后端
cam = cv2.VideoCapture(cv2.CAP_LIBCAMERA)
print(cv2.__version__)
print(cam.isOpened())
ret, frame = cam.read()
print(ret, frame is not None)

if ret:
    cv2.imwrite("test_libcamera.png", frame)

cam.release()

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.21 04:36:13