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

如何在高通RB5开发板上用HAL3/Camera2+OpenCV获取双MIPI摄像头视频?

问题描述

使用高通RB5开发套件搭配两颗OV9282 MIPI摄像头,尝试通过Gstreamer结合OpenCV访问双目摄像头时遇到以下问题:

  • 仅能显示单个摄像头画面
  • Gstreamer视频流无法传入cv2.VideoCapture供后续处理

现寻求通过HAL3/Camera2 API结合OpenCV访问双目摄像头的可行方案,以下是尝试的Gstreamer代码:

import cv2
from threading import Thread
from time import sleep
import gi

gi.require_version("Gst", "1.0")
from gi.repository import Gst, GLib

Gst.init(None)

main_loop = GLib.MainLoop()
thread = Thread(target=main_loop.run)
thread.start()

pipeline_str = """
    qtiqmmfsrc camera=1 ! video/x-raw, format=NV12, width=1280, height=720, framerate=15/1 ! videoconvert ! waylandsink 
"""
pipeline = Gst.parse_launch(pipeline_str)
pipeline.set_state(Gst.State.PLAYING)

pipeline_str2 = """
    qtiqmmfsrc camera=3 ! video/x-raw, format=NV12, width=1280, height=720, framerate=15/1 ! videoconvert ! waylandsink
"""
pipeline2 = Gst.parse_launch(pipeline_str2)
pipeline2.set_state(Gst.State.PLAYING)

cap = cv2.VideoCapture(pipeline_str, cv2.CAP_GSTREAMER)
cap2 = cv2.VideoCapture(pipeline_str2, cv2.CAP_GSTREAMER)

num = 0

while True:
    succes1, img = cap.read()
    succes2, img2 = cap2.read()

    if not succes1 or not succes2:
        break

    cv2.imshow('Img 1', img)
    cv2.imshow('Img 2', img2)

    k = cv2.waitKey(5)

    if k == 27:
        break
    elif k == ord('s'):
        cv2.imwrite('images/stereoLeft/imageL{}.png'.format(num), img)
        cv2.imwrite('images/stereoRight/imageR{}.png'.format(num), img2)
        print('images saved!')
        num += 1

cap.release()
cap2.release()
cv2.destroyAllWindows()

pipeline.set_state(Gst.State.NULL)
pipeline2.set_state(Gst.State.NULL)
main_loop.quit()

原Gstreamer代码问题分析

  1. 资源冲突:同时通过Gst.parse_launch启动Pipeline,又用cv2.VideoCapture加载同一段Pipeline字符串,导致同一摄像头被两个进程抢占,无法正常工作。
  2. Sink组件错误:waylandsink是直接输出画面的显示组件,无法将视频流传递给OpenCV的VideoCapture,需替换为appsink作为OpenCV的输入源。

HAL3/Camera2 API + OpenCV 双目访问方案

高通RB5原生支持Camera2 API(基于HAL3),以下是Python环境下的实现方案:

1. 环境准备

  • 安装依赖:pip install opencv-python pycam2
  • 权限配置:Linux环境下将当前用户加入video组;Android环境下授予摄像头权限:adb shell pm grant com.your.package android.permission.CAMERA
  • 确认摄像头ID:通过pycam2的CameraManager.list_cameras()查看两颗OV9282的设备ID

2. 代码实现

import cv2
import numpy as np
from pycam2.camera2 import CameraManager, CameraDevice

# 初始化摄像头管理器
cam_manager = CameraManager()

# 查看可用摄像头(执行一次确认ID后可注释)
# print(cam_manager.list_cameras())

# 绑定双目摄像头(替换为实际ID)
cam_left = CameraDevice(cam_manager, camera_id=0)
cam_right = CameraDevice(cam_manager, camera_id=1)

# 配置摄像头参数
def configure_camera(cam):
    config = cam.create_default_configuration()
    config.set_preview_size((1280, 720))
    config.set_image_format("YUV_420_888")
    config.set_framerate(15)
    return config

config_left = configure_camera(cam_left)
config_right = configure_camera(cam_right)

# 启动摄像头
cam_left.start(config_left)
cam_right.start(config_right)

num = 0
while True:
    # 获取帧数据
    frame_left = cam_left.get_frame()
    frame_right = cam_right.get_frame()

    if frame_left is None or frame_right is None:
        break

    # YUV转BGR格式(适配OV9282输出)
    img_left = cv2.cvtColor(np.array(frame_left.to_yuv()), cv2.COLOR_YUV2BGR_NV12)
    img_right = cv2.cvtColor(np.array(frame_right.to_yuv()), cv2.COLOR_YUV2BGR_NV12)

    # 显示与保存
    cv2.imshow('Left Camera', img_left)
    cv2.imshow('Right Camera', img_right)

    k = cv2.waitKey(5)
    if k == 27:
        break
    elif k == ord('s'):
        cv2.imwrite(f'images/stereoLeft/imageL{num}.png', img_left)
        cv2.imwrite(f'images/stereoRight/imageR{num}.png', img_right)
        print('images saved!')
        num += 1

# 释放资源
cam_left.stop()
cam_right.stop()
cv2.destroyAllWindows()

3. 关键说明

  • 帧同步:如需严格双目帧同步,可通过Camera2的CaptureRequest配置同步捕获规则,确保左右帧同时采集
  • 格式适配:OV9282默认输出NV12格式,需对应使用COLOR_YUV2BGR_NV12转换参数

补充:修复原Gstreamer+OpenCV方案

若仍倾向使用Gstreamer,可修改Pipeline使用appsink替代waylandsink,并避免重复创建Pipeline:

import cv2

# 双目摄像头Gstreamer Pipeline(输出为OpenCV兼容的BGR格式)
pipeline_left = "qtiqmmfsrc camera=1 ! video/x-raw, format=NV12, width=1280, height=720, framerate=15/1 ! videoconvert ! video/x-raw, format=BGR ! appsink"
pipeline_right = "qtiqmmfsrc camera=3 ! video/x-raw, format=NV12, width=1280, height=720, framerate=15/1 ! videoconvert ! video/x-raw, format=BGR ! appsink"

cap_left = cv2.VideoCapture(pipeline_left, cv2.CAP_GSTREAMER)
cap_right = cv2.VideoCapture(pipeline_right, cv2.CAP_GSTREAMER)

if not cap_left.isOpened() or not cap_right.isOpened():
    print("无法打开摄像头")
    exit()

num = 0
while True:
    ret_left, img_left = cap_left.read()
    ret_right, img_right = cap_right.read()

    if not ret_left or not ret_right:
        break

    cv2.imshow('Left', img_left)
    cv2.imshow('Right', img_right)

    k = cv2.waitKey(5)
    if k == 27:
        break
    elif k == ord('s'):
        cv2.imwrite(f'images/stereoLeft/imageL{num}.png', img_left)
        cv2.imwrite(f'images/stereoRight/imageR{num}.png', img_right)
        print('images saved!')
        num += 1

cap_left.release()
cap_right.release()
cv2.destroyAllWindows()

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.27 19:10:03