单目相机(Mono camera)在MATLAB中的表示与实例

1 概述

本文将介绍单目相机基本概念及其内参矩阵和外参矩阵在MATLAB下的表示方法,并分析车体坐标系到相机坐标系、相机坐标系的像素坐标系的转换关系,再给出在MATLAB中的相关类和函数,最后由简入难给出相关实用案例。

2 单目相机(Mono camera)

2.1 基本概念

通常来说,单目相机是指只有一个镜头且无法直接测量深度信息的相机。相对而言还有双目相机,具备深度测量的RGB-D相机等种类。

2.2 车体坐标系到相机坐标系

在博文《自车坐标系下的物体相对和绝对位置和速度计算》已经阐述了车体坐标系的基本概念,最常用的坐标系是“坐标系–前-左-上(FLU)”,如下图所示:
在这里插入图片描述
但是车体坐标系的坐标原点可选,一般不会限定,《自车坐标系下的物体相对和绝对位置和速度计算》中提到通常来说会选在车辆后轴中心。

相机坐标系通常是指以相机光学焦点为原点,镜头朝前为x轴方向,面向镜头右方为y轴防线,上方为z轴方向。这里,可以把车辆坐标系简单理解为世界坐标系,相机坐标系与车体坐标系的转换参数即为相机的外参(Camera Extrinsics),描述的相机位姿特征,与相机内参相对。相机的外参可以调整,而内参在相机定型后则已经固定了。

相机坐标系与车辆坐标系之间存在三个平移和三个旋转的关系。因此为了进行坐标系转换,需要知道相机在车辆坐标系中的位姿,即坐标和姿态。平移相对好理解,旋转的表示方法有多种,一般可以用欧式变换、旋转轴和欧拉角度或者四元数来表示。由于这块内容属于基础理论,理论成熟且篇幅有限,这里不作展开,总之在已知x、y、z三个方向位置和姿态(旋转角度)的情况下,可以求出两个坐标系下坐标点的转换关系。详细可以参考w维基百科《Rotation matrix》,或者中文版的《旋转矩阵》

2.3 相机坐标系到像素坐标系

相机坐标系到像素坐标系的变换参见博文《相机内参坐标系及其在MATLAB 中的表示》在这里插入图片描述

MATLAB中采用类 cameraIntrinsics描述相机内参矩阵——相机坐标系到像素坐标系之间的关系。
在这里插入图片描述

2.4 相关类和函数

2.4.1 monoCamera类

在MATLAB中表述单目相机的类是monoCamera类,该类的语法如下:

sensor = monoCamera(intrinsics,height);
sensor = monoCamera(intrinsics,height,Name,Value)

提供了两种常用的构造函数。

主要的属性如下:
在这里插入图片描述
Intrinsic即为相机的内参类,Height、SensorLocation描述了在车体坐标系中的三维坐标,Pictch、Yaw、Roll分别为Y、Z、X方向轴上的旋转角度,以上六个参数实际就是描述了相机的外参矩阵。

2.4.2 变换函数

函数解释
vehicleToImageConvert image coordinates to vehicle coordinates
vehicleToImageConvert vehicle coordinates to image coordinates

提供的两个函数vehicleToImage 和vehicleToImage可以将坐标点从车辆坐标系转换到像素坐标系,也可以将坐标点从像素坐标系转换到车辆坐标系,具体的转换代码其实我们在理解2.2和2.3节中相关变换的数学原理上其实可以不用去关注,只要知道有这个过程就可以了(这也是我个人比较喜欢的模式,对于成熟的原理只要理解数学推导,在有相关库例如OPENCV和语言知识的基础上,详细的代码设计可以不用关心,当然如果用于学习代码知识可以另当别论)。

3 实例分析

示例 1 重合

已知内参矩阵,且车辆坐标系与相机坐标系重合。求:车体正前方10m 远处的点在像素坐标系下的坐标。示例代码如下:

focalLength = [800 800];
principalPoint = [320 240];
imageSize = [480 640];
intrinsics = cameraIntrinsics(focalLength,principalPoint,imageSize);
height = 0.000001 ; % 高度无法设置为0,这里用0.000001代替
sensor = monoCamera(intrinsics,height);
xyVehicleLoc1 = [10 0]; % 车体正前方10m 远处的点
xyImageLoc1 = vehicleToImage(sensor,xyVehicleLoc1)

运行结果如下:

xyImageLoc1 =
  	319.9999  240.0001

可见,正前方10m的点,在像素坐标系下的位置为:(320,240)即principalPoint,位于图像的中心位置。

示例2 平移

在示例1的基础上,只改变车辆坐标系与相机坐标系在z轴上的差异:

focalLength = [800 800];
principalPoint = [320 240];
imageSize = [480 640];
intrinsics = cameraIntrinsics(focalLength,principalPoint,imageSize);
height = 1; % 高度设置为1m
sensor = monoCamera(intrinsics,height);
xyVehicleLoc1 = [10 0 1]; % 车体正前方10m 远处高度为1m的点
xyImageLoc1 = vehicleToImage(sensor,xyVehicleLoc1)

运行结果如下:

xyImageLoc1 =
  240.0000  160.0000

y方向设置为1m,高度(z方向)设置为2m,

xyVehicleLoc1 = [10 1 2]; % 车体正前方10m 远处高度为1m的点
xyImageLoc1 = vehicleToImage(sensor,xyVehicleLoc1)

示例3 旋转

相机位置相对车辆坐标系在y轴方向上有14°的旋转角度(直接拿的Help例子)。
在这里插入图片描述

focalLength = [800 800];
principalPoint = [320 240];
imageSize = [480 640];
intrinsics = cameraIntrinsics(focalLength,principalPoint,imageSize);
height = 2.18;
pitch = 14;
sensor = monoCamera(intrinsics,height,'Pitch',pitch);
xyVehicleLoc1 = [10 0];
xyImageLoc1 = vehicleToImage(sensor,xyVehicleLoc1)

运行结果如下:

xyImageLoc1 =
  320.0000  216.2296

进一步,将该坐标点xyImageLoc1绘制到像素坐标系,结果如下:

Ioriginal = imread('road.png');
figure
imshow(Ioriginal)
title('Original Image')

IvehicleToImage = insertMarker(Ioriginal,xyImageLoc1);
IvehicleToImage = insertText(IvehicleToImage,xyImageLoc1 + 5,'10 meters');
figure
imshow(IvehicleToImage)
title('Vehicle-to-Image Point')

运行结果如下:
在这里插入图片描述
更进一步,假设地面上某点在像素坐标系下的x、y坐标为(300 300),求在车辆坐标系下的坐标值。
注意这里求的是地面某点,因此实际z坐标值已知,为-height即-2.18,代码如下:

xyImageLoc2 = [300 300];
xyVehicleLoc2 = imageToVehicle(sensor,xyImageLoc2)

运行结果如下:

xyVehicleLoc2 = 1×2
    6.5959    0.1732

因此图像中x、y坐标为(300 300)的点对应到车辆坐标系下的实际位置为(6.5959 0.1732),距离车辆原点前方6.6m,左手放方向0.17m处。

参考

MATLAB官网《monocamera》:https://www.mathworks.com/help/driving/ref/monocamera.html#bvoy54v:
高翔:《视觉SLAM14讲》
维基百科《Rotation_matrix》:https://en.wikipedia.org/wiki/Rotation_matrix

  • 5
    点赞
  • 34
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
要让一个zed双目相机和一个单目相机同步拍摄,需要在代码使用多线程或多进程来同时控制相机的拍摄。在每个线程或进程,将调用zed相机单目相机的拍摄函数,并将它们同步,以确保它们在同一时间拍摄。 具体来说,可以使用Python的multiprocessing模块来实现多进程控制相机拍摄。首先,需要导入multiprocessing和相机的Python SDK。然后,可以创建两个进程,一个用于控制zed相机拍摄,另一个用于控制单目相机拍摄。在进程,可以使用相机SDK提供的同步函数,如sync_capture(),来确保它们在同一时间拍摄。最后,将两个进程合并在一起,以便它们同时运行。 下面是一个示例代码,用于控制zed相机单目相机同步拍摄: ``` import multiprocessing import zed_camera_sdk # zed相机SDK import mono_camera_sdk # 单目相机SDK def zed_capture(): # 初始化zed相机 zed = zed_camera_sdk.ZedCamera() zed.init() # 同步zed相机单目相机 zed.sync_start() # 开始拍摄 zed.capture() def mono_capture(): # 初始化单目相机 mono = mono_camera_sdk.MonoCamera() mono.init() # 同步zed相机单目相机 mono.sync_start() # 开始拍摄 mono.capture() if __name__ == '__main__': # 创建两个进程,一个用于zed相机,一个用于单目相机 zed_process = multiprocessing.Process(target=zed_capture) mono_process = multiprocessing.Process(target=mono_capture) # 启动进程 zed_process.start() mono_process.start() # 等待两个进程结束 zed_process.join() mono_process.join() ``` 需要注意的是,具体的代码实现需要根据相机的SDK和具体的硬件设备进行调整。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值