主要内容

在车辆坐标中使用检测注释视频

配置和使用monoCamera对象在视频显示器上显示以车辆坐标提供的信息。

概述

在录制的视频中显示车辆坐标记录的数据是地面真相标记和分析跟踪结果的重要组成部分。使用二维鸟瞰图可以帮助您了解整体环境,但有时很难将视频与鸟瞰图显示相关联。特别是,当使用第三方传感器时,这个问题会变得更严重,因为您无法访问传感器捕获的原始视频,并且需要使用单独的摄像机捕获的视频。

自动驾驶工具箱™提供monoCamera对象,用于方便车辆坐标和图像坐标之间的转换。本例读取安装在测试车辆上的视频传感器记录的数据。然后,它将数据显示在安装在同一辆车上的独立摄像机拍摄的视频中。数据和视频的记录速率如下:

  • 报告车道信息:每秒20次

  • 报告视觉对象:每秒10次

  • 视频帧率:每秒20帧

显示带有视频注释的帧

所选帧对应于视频片段的5.9秒,此时视频中有几个对象要显示。

设置视频阅读器和播放器videoFile =“01 _city_c2s_fcw_10s.mp4”;videoReader = videreader (videoFile);videoPlayer = vision.DeployableVideoPlayer;跳转到所需的帧时间= 5.9;videoReader。CurrentTime = time;frameWithoutAnnotations = readFrame(videereader);imshow (frameWithoutAnnotations);标题(“原始视频帧”

图中包含一个轴对象。标题为Original Video Frame的axes对象包含一个image类型的对象。

获取相应的记录数据。

recordingFile =“01 _city_c2s_fcw_10s_sensor.mat”;[visionObjects, laneReports, timeStep, numSteps] = readDetectionsFile(recordingFile);currentStep = round(time / timeStep) + 1;videoDetections = processDetections(visionObjects(currentStep));laneBoundaries = processLanes(laneReports(currentStep));设置monoCamera对象用于视频显示sensor = setupMonoCamera(视频阅读器);frameWithAnnotations = updateDisplay(frameWithAnnotations, sensor, videoDetections, laneBoundaries);imshow (frameWithAnnotations);标题(“注释视频帧”

图中包含一个轴对象。标题为Annotated Video Frame的axes对象包含一个image类型的对象。

显示带有视频注释的剪辑

要显示带有注释的视频剪辑,只需逐帧重复注释。视频显示,汽车略微上下倾斜,从而改变了俯仰角。没有尝试去补偿这种俯仰运动。因此,从车辆坐标到图像坐标的转换在某些帧上有点不准确。

将时间重置为零currentStep = 0;重置记录的数据时间步长videoReader。CurrentTime = 0;重置视频阅读器时间currentStep < numSteps && hasFrame(videoReader)%更新场景计数器currentStep = currentStep + 1;获取当前时间抽搐准备检测到跟踪器videoDetections = processDetections(visionObjects(currentStep), videoDetections);%进程通道laneBoundaries = processLanes(laneReports(currentStep));使用报告对象的注释更新视频帧frameWithoutAnnotations = readFrame(videereader);frameWithAnnotations = updateDisplay(frameWithAnnotations, sensor, videoDetections, laneBoundaries);记录的数据以每秒20帧的速率获得。暂停50毫秒,以获得更真实的显示速率。如果你%在这个循环中处理数据和表单轨道,您不需要这个%的停顿。暂停(0.05 - toc);显示带注释的帧放像机(frameWithAnnotations);结束

为视频显示创建单声道摄像头

setupMonoCamera函数返回monoCamera传感器对象,用于将车辆坐标中的位置转换为图像坐标。

了解相机的内、外标定参数是实现像素坐标与车辆坐标准确转换的关键。

首先定义相机的内在参数。该函数中的参数是基于相机模型进行估计的。若要获取相机的参数,请使用相机校准器应用程序。

因为这个例子中的数据失真很小,所以这个函数忽略了镜头失真系数。参数接下来存储在cameraIntrinsics对象。

接下来,定义相机外部。摄像头外设与摄像头安装在汽车上的方式有关。挂载包括以下属性:

  • 高度:离地面的安装高度,单位为米。

  • 俯仰角:相机的俯仰角,以度为单位,正角在地平线以下,朝向地面。在大多数情况下,相机的倾角略低于地平线。

  • 滚转:相机绕轴的滚转。例如,如果视频是颠倒的,使用roll = 180。

  • 偏航:相机横向的角度,正片在正片的方向上y-轴(向左)。例如,前置摄像头的偏航角为0度,后置摄像头的偏航角为180度。

函数传感器= setupMonoCamera(vidReader)从视频信息定义相机的内在特性focalLength = [1260 1100];% [fx, fy] %像素principalPoint = [360 245];% [cx, cy] %像素imageSize = [vidReader.]高度,vidReader.width];% [numRows, numColumns] %像素intrinsic = cameraIntrinsics(focalLength, principalPoint, imageSize);定义相机安装(相机外部)mountingHeight = 1.45;%距离地面的高度,单位为米mountingPitch = 1.25;相机的% pitch(以度为单位)mountingRoll = 0.15;%相机滚动度mountingYaw = 0;%相机偏航度传感器= monoCamera(intrinsic, mountingHeight,...“节”mountingPitch,...“滚”mountingRoll,...“偏航”, mountingYaw);结束

使用Mono Camera对象更新显示

updateDisplay函数显示视频帧顶部的所有对象注释。

显示更新包括以下步骤:

  1. 使用monoCamera传感器将报告的检测转换为边界框并注释帧。

  2. 使用insertLaneBoundary方法parabolicLaneBoundary对象插入车道注释。

函数frame = updateDisplay(帧,传感器,视频检测,车道边界)为边界框分配内存bboxes = 0(数字(videoDetections), 4);创建边界框i = 1:数字(videoDetections)%使用单摄像机传感器转换车辆坐标中的位置%到图像坐标中的位置。%指出:% 1。对象的宽度被报告并用于计算对象周围边框的%大小(每个边框宽度的一半)%)。没有报告物体的高度。相反,%函数使用汽车的高/宽比为0.85,汽车的高/宽比为3%的行人。% 2。报告的位置是在地面物体的中心%级别,即包围框的底部。xyLocation1 = vehicleToImage(传感器,videoDetections(i)。position ' + [0,videoDetections(i).width /2]);xyLocation2 = vehicleToImage(传感器,videoDetections(i)。position ' - [0,videoDetections(i).width /2]);dx = xyLocation2(1) - xyLocation1(1);根据对象类定义高/宽比如果比较字符串(videoDetections .labels(我),“汽车”) dy = dx * 0.85;elseif比较字符串(videoDetections .labels(我),“行人”) dy = dx * 3;其他的Dy = dx;结束估计车辆周围的包围框。减去高度%边框来定义左上角。bboxes(i,:) =[(xyLocation1 - [0, dy]), dx, dy];结束%添加标签labels = {videoDetections(:).labels}';为框架添加边框如果~isempty(标签)frame = insertObjectAnnotation(帧,“矩形”,盒子,标签,...“颜色”,“黄色”,“字形大小”10“TextBoxOpacity”8,“线宽”2);结束显示视频帧上的车道边界xRangeVehicle = [1,100];xPtsInVehicle = linspace(xRangeVehicle(1), xRangeVehicle(2), 100)';frame = insertLaneBoundary(frame, laneBoundaries(1), sensor, xPtsInVehicle,...“颜色”,“红色”);frame = insertLaneBoundary(frame, laneBoundaries(2), sensor, xPtsInVehicle,...“颜色”,“绿色”);结束

总结

此示例显示如何创建monoCamera传感器对象,并使用它来显示由单独摄像机捕获的视频上的车辆坐标中描述的对象。尝试使用记录的数据和你自己的摄像机。试着校准你的相机来创建一个monoCamera这允许从车辆坐标到图像坐标的转换,反之亦然。

金宝app支持功能

readDetectionsFile—读取记录的传感器数据文件。记录的数据在单个结构中,该结构被分为四个部分结构体数组。本例只使用了以下两个数组:

  1. laneReports,一个结构体数组,它报告车道的边界。它有这些字段:而且正确的.数组的每个元素对应于不同的时间步长。这两个而且正确的是包含这些字段的结构:isValid,信心,boundaryType,抵消,headingAngle,曲率

  2. visionObjects,一个结构数组,报告检测到的视觉对象。它有字段numObjects(整数),对象(结构体).数组的每个元素对应于不同的时间步长。对象是一个结构体数组,其中每个元素都是一个单独的对象,包含以下字段:id,分类,位置(x, y, z),速度(vx; v; vz),大小(dx, dy, dz).注意:z = v = vz = dx = dz = 0

函数[visionObjects, laneReports, timeStep, numSteps] = readDetectionsFile(filename) A = load(strcat(filename));visionObjects = A.vision;laneReports = A.lane;准备一些时间变量timeStep = 0.05;% Lane数据每50毫秒提供一次numSteps = numel(视觉对象);记录的时间步数结束

processDetections-读取记录的视觉检测。这个例子只提取了以下属性:

  1. 位置:二维(x, y)车辆坐标中的数组

  2. 宽度:视频传感器报告的物体宽度(注意:传感器不报告物体尺寸的任何其他尺寸。)

  3. 标签:报告对象的分类

函数videoDetections = processDetections(visionData, videoDetections)%视频传感器以整数形式报告分类值%(从0开始)ClassificationValues = {“未知”,不知名的小的,未知的大的,...“行人”,“自行车”,“汽车”,“卡车”,“障碍”};%该帧中传感器报告的对象总数numVideoObjects = visionData.numObjects;视频对象每秒只报告10次,但是视频对象每秒只报告10次%的帧速率为每秒20帧。以防止注释从%忽明忽暗,此函数返回前一个函数的值% timestep,如果没有视频对象。如果numVideoObjects == 0如果Nargin == 1返回一个结果,即使之前没有值videoDetections = struct(“职位”{},“标签”{},“宽度”, {});结束返回其他的为视频检测的相关属性准备一个容器videoDetections = struct(“职位”[],“标签”[],“宽度”[]);i = 1:numVideoObjects videoDetections(i)。width = visionData.object(i).size(2);videoDetections(我)。位置= visionData.object(i).position(1:2);videoDetections(我)。标签= ClassificationValues{visionData.object(i)。分类+ 1};结束结束结束

processLanes-读取报告的车道信息,并将其转换为parabolicLaneBoundary对象。

车道边界根据laneReports从录音中。传感器报告车道作为抛物线模型的参数:% y = 一个 x 2 + b x + c

函数laneBoundaries = processLanes(laneReports)返回处理过的车道边界边界类型信息类型= {“无名”,“固体”,“冲”,“无名”,“BottsDots”,...“无名”,“无名”,“DoubleSolid”};读取此帧记录的车道报告leftLane = lanreports .left;rightLane = lanreports .right;为左右车道边界创建抛物线对象leftParams = cast([leftLane.]曲率,leftLane。headingAngle,左Lane.offset],“双”);leftBoundaries =抛物线界线(leftParams);leftBoundaries。BoundaryType = types{leftLane.boundaryType};rightParams = cast([rightLane.]曲率,rightLane。headingAngle,正确的Lane.offset],“双”);右边界=抛物线边界(右params);rightBoundaries。BoundaryType = types{rightLane.boundaryType};laneBoundaries = [leftBoundaries, rightBoundaries];结束

另请参阅

应用程序

功能

对象

相关的话题