目录
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 变换函数
函数 | 解释 |
---|---|
vehicleToImage | Convert image coordinates to vehicle coordinates |
vehicleToImage | Convert 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