OAK相机:多相机硬件同步拍摄

2023-10-23 21:59
文章标签 同步 相机 硬件 拍摄 oak

本文主要是介绍OAK相机:多相机硬件同步拍摄,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

OAK相机:多相机硬件同步拍摄

  • 传感器同步
  • 硬件同步信号
    • FSYNC信号
    • STROBE信号
  • 硬件接线
    • 硬件设备
    • 接线步骤
  • 软件驱动
  • 参考文献

传感器同步

目前主要有两种方法来同步不同传感器的信息(帧、IMU数据包、ToF等):

  • 硬件同步(基于硬件信号触发,同步精度较高,需要硬件支持)
  • 软件同步(基于时间戳或序列号同步,同步精度较低,无需硬件支持)

此博客重点介绍硬件同步,它允许在多个相机传感器之间精确同步,并可能与其他硬件同步,如闪光灯LED、外部IMU或其他相机。

硬件同步信号

FSYNC信号

FSYNC/FSIN(帧同步)信号是一个脉冲,在开始捕获每个帧时被驱动为高电平。它的长度与曝光时间不成正比,可以是输入或输出,工作电压是1.8V。

在双目立体相机(OAK-D*)上,我们希望双目黑白相机是完全同步的,所以一个相机传感器(如左相机)的FSYNC设置为INPUT(输入),而另一个相机传感器(如右相机)的FSYNC设置为OUTPUT(输出)。在这样的配置中,右相机驱动左相机。

注意:目前,只有OV9282/OV9782可以输出FSYNC信号,而IMX378/477/577/等应该也有这个能力,但还不支持(所以这些信号不能驱动FSYNC信号,只能被它驱动)。AR0234只支持输入FSYNC信号。

如果我们想用外部信号驱动相机,我们需要将FSIN设置为相机传感器的INPUT。将一个信号发生器连接到所有的FSIN引脚上,这样相机将根据信号发生器的触发信号捕获每一帧图像。

STROBE信号

STROBE信号是图像传感器的输出,在图像传感器的曝光期间是有效的(高电平)。它可以用来驱动外部的LED照明,所以照明只在曝光时间内激活,而不是持续开启,这将减少功耗和发热。

在OAK-D-Pro系列相机上使用STROBE信号(它有板载照明红外LED和红外激光点阵发射器)来驱动激光/LED。

硬件接线

硬件设备

我们使用的硬件设备如下:
OV9782广角相机 × 4
OAK-FFC-4P摄像头模组 × 1

OV9782广角相机产品特点:

  • CMOS感光
  • 全局快门
  • 最大帧率:120 FPS
  • 最大分辨率: 1MP(1280×800)
  • DFOV:89.5°
  • HFOV:80°
  • VFOV:55°
  • 对焦范围:固定焦点:19.6 cm – ∞

OAK-FFC-4P摄像头模组属于分体式OAK,可以通过软排线接入4个独立的MIPI相机模块,其产品特点有:

  • 4T算力;
  • 4K H.265推流;
  • 厘米级测量精度;
  • 支持的平台和语言:Windows10、Ubuntu、树莓派、linux、macOS、Jetson、Python、C++、ROS、Android(需depthai≥2.16.0)。

接线步骤

1、首先,使用跳线将每根电缆上的 FSIN 测试点连接到相应相机板上的 FSIN 引脚(也可以直接将相机板上的所有FSIN引脚直接相连):
在这里插入图片描述
2、然后,将4个OV9782广角相机通过排线连接到OAK-FFC-4P摄像头模组:
在这里插入图片描述
3、最后,给摄像头模组供电,并通过USB接入电脑PC中。

软件驱动

编写测试代码和打印设备时间戳,camera_driver.py文件如下:

import depthai as dai
import time
import cv2
import collectionsset_fps = 30class FPS:def __init__(self, window_size=30):self.dq = collections.deque(maxlen=window_size)self.fps = 0def update(self, timestamp=None):if timestamp == None: timestamp = time.monotonic()count = len(self.dq)if count > 0: self.fps = count / (timestamp - self.dq[0])self.dq.append(timestamp)def get(self):return self.fpscam_list = ['rgb', 'left', 'right', 'camd']
cam_socket_opts = {'rgb'  : dai.CameraBoardSocket.RGB,   # Or CAM_A'left' : dai.CameraBoardSocket.LEFT,  # Or CAM_B'right': dai.CameraBoardSocket.RIGHT, # Or CAM_C'camd' : dai.CameraBoardSocket.CAM_D,
}pipeline = dai.Pipeline()
cam = {}
xout = {}
for c in cam_list:cam[c] = pipeline.create(dai.node.MonoCamera)cam[c].setResolution(dai.MonoCameraProperties.SensorResolution.THE_800_P)if c == 'rgb':cam[c].initialControl.setFrameSyncMode(dai.CameraControl.FrameSyncMode.OUTPUT)else:cam[c].initialControl.setFrameSyncMode(dai.CameraControl.FrameSyncMode.INPUT)cam[c].setBoardSocket(cam_socket_opts[c])xout[c] = pipeline.create(dai.node.XLinkOut)xout[c].setStreamName(c)cam[c].out.link(xout[c].input)config = dai.Device.Config()
config.board.gpio[6] = dai.BoardConfig.GPIO(dai.BoardConfig.GPIO.OUTPUT,dai.BoardConfig.GPIO.Level.HIGH)with dai.Device(config) as device:device.startPipeline(pipeline)q = {}fps_host = {}  # FPS computed based on the time we receive frames in appfps_capt = {}  # FPS computed based on capture timestamps from devicefor c in cam_list:q[c] = device.getOutputQueue(name=c, maxSize=1, blocking=False)cv2.namedWindow(c, cv2.WINDOW_NORMAL)cv2.resizeWindow(c, (640, 480))fps_host[c] = FPS()fps_capt[c] = FPS()while True:frame_list = []for c in cam_list:pkt = q[c].tryGet()if pkt is not None:fps_host[c].update()fps_capt[c].update(pkt.getTimestamp().total_seconds())print(c+":",pkt.getTimestampDevice())frame = pkt.getCvFrame()cv2.imshow(c, frame)print("-------------------------------")# print("\rFPS:",#       *["{:6.2f}|{:6.2f}".format(fps_host[c].get(), fps_capt[c].get()) for c in cam_list],#       end='', flush=True)key = cv2.waitKey(1)if key == ord('q'):break

运行

python camera_driver.py

参考文献

1、通过硬件触发信号实现OAK多相机之间的同步拍摄
2、官方文档:硬件同步
3、官方文档:oak-ffc-4p
4、原理图
5、oak_deptahi_external_trigger_fsync.py

#!/usr/bin/env python3
import depthai as dai
import cv2
import timepipeline = dai.Pipeline()camRgb = pipeline.create(dai.node.ColorCamera)
camRgb.setColorOrder(dai.ColorCameraProperties.ColorOrder.RGB)
camRgb.setIspScale(2,3)
camRgb.initialControl.setFrameSyncMode(dai.CameraControl.FrameSyncMode.INPUT)
camRgb.initialControl.setExternalTrigger(4,3)xoutRgb = pipeline.create(dai.node.XLinkOut)
xoutRgb.setStreamName("color")
camRgb.isp.link(xoutRgb.input)monoLeft = pipeline.create(dai.node.MonoCamera)
monoLeft.setResolution(dai.MonoCameraProperties.SensorResolution.THE_720_P)
monoLeft.setBoardSocket(dai.CameraBoardSocket.LEFT)
monoLeft.initialControl.setFrameSyncMode(dai.CameraControl.FrameSyncMode.INPUT)
monoLeft.initialControl.setExternalTrigger(4,3)xoutLeft = pipeline.create(dai.node.XLinkOut)
xoutLeft.setStreamName("left")
monoLeft.out.link(xoutLeft.input)monoRight = pipeline.createMonoCamera()
monoRight.setResolution(dai.MonoCameraProperties.SensorResolution.THE_720_P)
monoRight.setBoardSocket(dai.CameraBoardSocket.RIGHT)
monoRight.initialControl.setFrameSyncMode(dai.CameraControl.FrameSyncMode.INPUT)
monoRight.initialControl.setExternalTrigger(4,3)xoutRight = pipeline.create(dai.node.XLinkOut)
xoutRight.setStreamName("right")
monoRight.out.link(xoutRight.input)# Connect to device with pipeline
with dai.Device(pipeline) as device:arr = ['left', 'right', 'color']queues = {}frames = {}for name in arr:queues[name] = device.getOutputQueue(name)print("Starting...")while True:for name in arr:if queues[name].has():frames[name]=queues[name].get().getCvFrame()for name, frame in frames.items():cv2.imshow(name, frame)key = cv2.waitKey(1)if key == ord('q'):break

这篇关于OAK相机:多相机硬件同步拍摄的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/270712

相关文章

Java中将异步调用转为同步的五种实现方法

《Java中将异步调用转为同步的五种实现方法》本文介绍了将异步调用转为同步阻塞模式的五种方法:wait/notify、ReentrantLock+Condition、Future、CountDownL... 目录异步与同步的核心区别方法一:使用wait/notify + synchronized代码示例关键

0基础租个硬件玩deepseek,蓝耘元生代智算云|本地部署DeepSeek R1模型的操作流程

《0基础租个硬件玩deepseek,蓝耘元生代智算云|本地部署DeepSeekR1模型的操作流程》DeepSeekR1模型凭借其强大的自然语言处理能力,在未来具有广阔的应用前景,有望在多个领域发... 目录0基础租个硬件玩deepseek,蓝耘元生代智算云|本地部署DeepSeek R1模型,3步搞定一个应

C#实现获取电脑中的端口号和硬件信息

《C#实现获取电脑中的端口号和硬件信息》这篇文章主要为大家详细介绍了C#实现获取电脑中的端口号和硬件信息的相关方法,文中的示例代码讲解详细,有需要的小伙伴可以参考一下... 我们经常在使用一个串口软件的时候,发现软件中的端口号并不是普通的COM1,而是带有硬件信息的。那么如果我们使用C#编写软件时候,如

详谈redis跟数据库的数据同步问题

《详谈redis跟数据库的数据同步问题》文章讨论了在Redis和数据库数据一致性问题上的解决方案,主要比较了先更新Redis缓存再更新数据库和先更新数据库再更新Redis缓存两种方案,文章指出,删除R... 目录一、Redis 数据库数据一致性的解决方案1.1、更新Redis缓存、删除Redis缓存的区别二

如何安装HWE内核? Ubuntu安装hwe内核解决硬件太新的问题

《如何安装HWE内核?Ubuntu安装hwe内核解决硬件太新的问题》今天的主角就是hwe内核(hardwareenablementkernel),一般安装的Ubuntu都是初始内核,不能很好地支... 对于追求系统稳定性,又想充分利用最新硬件特性的 Ubuntu 用户来说,HWEXBQgUbdlna(Har

Nacos集群数据同步方式

《Nacos集群数据同步方式》文章主要介绍了Nacos集群中服务注册信息的同步机制,涉及到负责节点和非负责节点之间的数据同步过程,以及DistroProtocol协议在同步中的应用... 目录引言负责节点(发起同步)DistroProtocolDistroSyncChangeTask获取同步数据getDis

基于MySQL Binlog的Elasticsearch数据同步实践

一、为什么要做 随着马蜂窝的逐渐发展,我们的业务数据越来越多,单纯使用 MySQL 已经不能满足我们的数据查询需求,例如对于商品、订单等数据的多维度检索。 使用 Elasticsearch 存储业务数据可以很好的解决我们业务中的搜索需求。而数据进行异构存储后,随之而来的就是数据同步的问题。 二、现有方法及问题 对于数据同步,我们目前的解决方案是建立数据中间表。把需要检索的业务数据,统一放到一张M

服务器集群同步时间手记

1.时间服务器配置(必须root用户) (1)检查ntp是否安装 [root@node1 桌面]# rpm -qa|grep ntpntp-4.2.6p5-10.el6.centos.x86_64fontpackages-filesystem-1.41-1.1.el6.noarchntpdate-4.2.6p5-10.el6.centos.x86_64 (2)修改ntp配置文件 [r

基于UE5和ROS2的激光雷达+深度RGBD相机小车的仿真指南(五):Blender锥桶建模

前言 本系列教程旨在使用UE5配置一个具备激光雷达+深度摄像机的仿真小车,并使用通过跨平台的方式进行ROS2和UE5仿真的通讯,达到小车自主导航的目的。本教程默认有ROS2导航及其gazebo仿真相关方面基础,Nav2相关的学习教程可以参考本人的其他博客Nav2代价地图实现和原理–Nav2源码解读之CostMap2D(上)-CSDN博客往期教程: 第一期:基于UE5和ROS2的激光雷达+深度RG

【STM32】SPI通信-软件与硬件读写SPI

SPI通信-软件与硬件读写SPI 软件SPI一、SPI通信协议1、SPI通信2、硬件电路3、移位示意图4、SPI时序基本单元(1)开始通信和结束通信(2)模式0---用的最多(3)模式1(4)模式2(5)模式3 5、SPI时序(1)写使能(2)指定地址写(3)指定地址读 二、W25Q64模块介绍1、W25Q64简介2、硬件电路3、W25Q64框图4、Flash操作注意事项软件SPI读写W2