为什么要进行标定?
一辆自动驾驶车辆会安装多个传感器,需要通过传感器标定来确定相互之间的坐标关系,从而将多个传感器数据整合为“一个传感器”。因此,准确的传感器标定是实现智能车辆多传感器感知和定位系统的先决条件。
传感器标定的基本原理是将已知的被测量(亦即标准量)输入给待标定的传感器,同时得到传感器的输出量,对输入量和输出量进行对比处理,得到一系列表征两者对应关系的标定曲线,进而得到传感器性能指标的实测结果。
分类
传感器标定分为内参数标定和外参数标定:
内参数是传感器自身固有性质,决定传感器的内部映射关系,如Camera的焦距和镜头畸变、Lidar内部激光发射器坐标与激光雷达坐标装置之间的转换关系;
而外参指的是传感器相对位置朝向对于世界坐标系的旋转和平移变换关系,通常用三维的旋转矩阵R3×3(3个自由度)和平移向量T3×3(3个自由度)共6个自由度表示,以确定传感器与外部坐标系之间的转换关系。
大多数传感器在安装后需要进行标定,以确保传感器测量的准确性。
关于坐标系
以Camera为例,其涉及的坐标系包括像素坐标系、图像坐标系、相机坐标系和世界坐标系,标定就是为了获取以上四大坐标系之间的对应关系,即获取外参矩阵。
在标定的时候,如果物体在距离相机的不同位置,那么我们就必须在不同的位置对相机做标定。
简单点来理解就是,当物体离相机远的时候,在图像上就很小,那么一个像素代表的实际尺寸就大,当物体离相机近的时候,那么成像效果就大,一个像素代表的实际物体尺寸就小。因此,对于每一个位置都需要去标定。
像素坐标系:
像素坐标就是像素在图像中的位置。一般像素坐标系的左上角的顶点就是原点,水平向右是u,垂直向下是v轴,单位pixel。
图像坐标系:
在像素坐标系中,每个像素的坐标是用像素来表示的,然而,像素的表示方法却不能反应图像中物体的物力尺寸,因此,有必要将像素坐标转换为图像坐标。
将像素坐标系的原点平移到图像的中心,就定为图像坐标系的原点,图像坐标系的 x轴与像素坐标系的 u 轴平行,方向相同,而图像坐标系的 y 轴与像素坐标系的 v 轴平行,方向相同。
相机坐标系:
相机坐标系是以相机的光轴作为Z轴,光线在相机光学系统的中心位置就是原点Oc(实际上就是透镜的中心),相机坐标系的水平轴Xc与垂直轴Yc分别于图像坐标系的 X轴和 Y 轴平行。在图中,相机坐标系的原点与图像坐标系的原点之间的距离OcOi之间的距离为 f(也就是焦距)。
世界坐标系:
世界坐标系是图像与真实物体之间的一个映射关系。如果是单目视觉的话,主要就
是真实物体尺寸与图像尺寸的映射关系。如果是多目视觉的话,那么就需要知道多个相机之间的关系,这个关系就需要在同一个坐标系下进行换算。在下图中,世界坐标系的原点是 Ow,而 Xw,Yw,Zw 轴并不是与其他坐标系平行的,而是有一定的角度,并且有一定的平移。当对相机坐标系安装一定的参数,分别绕着 X,Y,Z 轴做平移和旋转后,就得到在世界坐标系中的坐标,因此从世界坐标系变换到相机坐标系即可用一个旋转矩阵 R 和一个平移向量 T 表示即可,由于世界坐标系到摄像头坐标系的转换关系是摄像头在世界坐标系下的位置姿态矩阵,因此这个 R 和 T 被称为相机的外参矩阵。
至于像素到图像、图像到相机之间的转换在此不再赘述,由于这两者之间的转换是发生在相机内部之间的转换,因此相乘的结果就是内参,感兴趣的读者可以自行搜索研究。
图像畸变及畸变矫正
由于相机多为透镜,所以生成的图像看起来会产生一定的形变、扭曲或者其他的变化。图像畸变的类型可分为径向畸变和切向畸变。
径向畸变:
在自动驾驶汽车上,影像摄像头工作的径向畸变有两种:桶形畸变和枕形畸变,一般广角镜头为桶形畸变,长焦/变焦镜头为枕形畸变。如下图所示。
切向畸变
切向畸变可以这样理解,当透镜与成像平面不行时,就产生了畸变,类似于透视变换。
在通常的单目视觉应用中,求得内参和畸变参数后,就可以对新拍摄的图像做变换和矫正。矫正完拍摄的图像之后,就可以对图像做其他处理了。
对于双目视觉而言,需要用到世界坐标系。对单目视觉做完内参和畸变参数的矫正之后,就可以用这些变换后的图像,同时结合世界坐标系实现定位或者其他用途了。
标定方法
外参标定方法通常可分为无目标(targetless)标定和基于目标(target-based)标定。前者不需要特殊目标,是在自然环境中进行的,利用自然环境中的静止物体(如树木、电线杆、路灯杆、交通标志牌等)和清晰车道线进行标定;后者需要一个特殊的控制场,并有一个真实值(GT)目标,如棋盘、多边形棋盘(张氏标定法),通过棋盘格的角点来建立对应关系。因此,基于目标的方法可以使用有关目标的先验知识,增强标定结果。基于目标方法比无目标方法更精确。
举例来说,就是拍摄 N 张不同视角下类似于下图所示的标定板的照片,根据此标定板的实际尺寸,在电脑里假定了一个多长多宽的假想标定板图像,而标定的过程就是所有拍摄到的标定板照片都应该往我假定的标定板靠,如果对不上,那么就有系数上的关系,这个系数上的关系就是我们要标定的参数。
内参标定通常采用目标法。常用的摄像头内参标定方法是张氏标定棋盘法。除了棋盘格图案外,还有一个常见的圆网格,用于标定摄像头内参。一些激光雷达内参标定方法是通过框或面墙执行的。
总结
拓展学习
整车测试之车载必修课(台架&路测&智能驾驶&智能座舱&车载自动化)
最后:
可以到我的个人号:atstudy-js,可以免费领取一份10G软件测试工程师面试宝典文档资料。以及相对应的视频学习教程免费分享!其中包括了有基础知识、Linux必备、Mysql数据库、抓包工具、接口测试工具、测试进阶-Python编程、Web自动化测试、APP自动化测试、接口自动化测试、测试高级持续集成、测试架构开发测试框架、性能测试等。
这些测试资料,对于做【软件测试】的朋友来说应该是最全面最完整的备战仓库,这个仓库也陪伴我走过了最艰难的路程,希望也能帮助到你!
我正在学习如何使用Nokogiri,根据这段代码我遇到了一些问题:require'rubygems'require'mechanize'post_agent=WWW::Mechanize.newpost_page=post_agent.get('http://www.vbulletin.org/forum/showthread.php?t=230708')puts"\nabsolutepathwithtbodygivesnil"putspost_page.parser.xpath('/html/body/div/div/div/div/div/table/tbody/tr/td/div
总的来说,我对ruby还比较陌生,我正在为我正在创建的对象编写一些rspec测试用例。许多测试用例都非常基础,我只是想确保正确填充和返回值。我想知道是否有办法使用循环结构来执行此操作。不必为我要测试的每个方法都设置一个assertEquals。例如:describeitem,"TestingtheItem"doit"willhaveanullvaluetostart"doitem=Item.new#HereIcoulddotheitem.name.shouldbe_nil#thenIcoulddoitem.category.shouldbe_nilendend但我想要一些方法来使用
很好奇,就使用rubyonrails自动化单元测试而言,你们正在做什么?您是否创建了一个脚本来在cron中运行rake作业并将结果邮寄给您?git中的预提交Hook?只是手动调用?我完全理解测试,但想知道在错误发生之前捕获错误的最佳实践是什么。让我们理所当然地认为测试本身是完美无缺的,并且可以正常工作。下一步是什么以确保他们在正确的时间将可能有害的结果传达给您? 最佳答案 不确定您到底想听什么,但是有几个级别的自动代码库控制:在处理某项功能时,您可以使用类似autotest的内容获得关于哪些有效,哪些无效的即时反馈。要确保您的提
关闭。这个问题是opinion-based.它目前不接受答案。想要改进这个问题?更新问题,以便editingthispost可以用事实和引用来回答它.关闭4年前。Improvethisquestion我想在固定时间创建一系列低音和高音调的哔哔声。例如:在150毫秒时发出高音调的蜂鸣声在151毫秒时发出低音调的蜂鸣声200毫秒时发出低音调的蜂鸣声250毫秒的高音调蜂鸣声有没有办法在Ruby或Python中做到这一点?我真的不在乎输出编码是什么(.wav、.mp3、.ogg等等),但我确实想创建一个输出文件。
给定这段代码defcreate@upgrades=User.update_all(["role=?","upgraded"],:id=>params[:upgrade])redirect_toadmin_upgrades_path,:notice=>"Successfullyupgradeduser."end我如何在该操作中实际验证它们是否已保存或未重定向到适当的页面和消息? 最佳答案 在Rails3中,update_all不返回任何有意义的信息,除了已更新的记录数(这可能取决于您的DBMS是否返回该信息)。http://ar.ru
我在我的项目目录中完成了compasscreate.和compassinitrails。几个问题:我已将我的.sass文件放在public/stylesheets中。这是放置它们的正确位置吗?当我运行compasswatch时,它不会自动编译这些.sass文件。我必须手动指定文件:compasswatchpublic/stylesheets/myfile.sass等。如何让它自动运行?文件ie.css、print.css和screen.css已放在stylesheets/compiled。如何在编译后不让它们重新出现的情况下删除它们?我自己编译的.sass文件编译成compiled/t
我正在寻找执行以下操作的正确语法(在Perl、Shell或Ruby中):#variabletoaccessthedatalinesappendedasafileEND_OF_SCRIPT_MARKERrawdatastartshereanditcontinues. 最佳答案 Perl用__DATA__做这个:#!/usr/bin/perlusestrict;usewarnings;while(){print;}__DATA__Texttoprintgoeshere 关于ruby-如何将脚
Rackup通过Rack的默认处理程序成功运行任何Rack应用程序。例如:classRackAppdefcall(environment)['200',{'Content-Type'=>'text/html'},["Helloworld"]]endendrunRackApp.new但是当最后一行更改为使用Rack的内置CGI处理程序时,rackup给出“NoMethodErrorat/undefinedmethod`call'fornil:NilClass”:Rack::Handler::CGI.runRackApp.newRack的其他内置处理程序也提出了同样的反对意见。例如Rack
在选择我想要运行操作的频率时,唯一的选项是“每天”、“每小时”和“每10分钟”。谢谢!我想为我的Rails3.1应用程序运行调度程序。 最佳答案 这不是一个优雅的解决方案,但您可以安排它每天运行,并在实际开始工作之前检查日期是否为当月的第一天。 关于ruby-如何每月在Heroku运行一次Scheduler插件?,我们在StackOverflow上找到一个类似的问题: https://stackoverflow.com/questions/8692687/
我有一个对象has_many应呈现为xml的子对象。这不是问题。我的问题是我创建了一个Hash包含此数据,就像解析器需要它一样。但是rails自动将整个文件包含在.........我需要摆脱type="array"和我该如何处理?我没有在文档中找到任何内容。 最佳答案 我遇到了同样的问题;这是我的XML:我在用这个:entries.to_xml将散列数据转换为XML,但这会将条目的数据包装到中所以我修改了:entries.to_xml(root:"Contacts")但这仍然将转换后的XML包装在“联系人”中,将我的XML代码修改为