电子工程师技术服务社区
公告
登录
|
注册
首页
技术问答
厂商活动
正点原子
板卡试用
资源库
下载
文章
社区首页
文章
【7天搞定视觉SLAM】第四天——相机与图像
分 享
扫描二维码分享
【7天搞定视觉SLAM】第四天——相机与图像
slam
hero_chao
关注
发布时间: 2020-04-21
丨
阅读: 1419
# 一、相机 ## 1.相机模型 ![](https://cf02.ickimg.com/bbsimages/202004/caa6b27dfbdcf18003cc2f2eb358fe91.png) 视觉SLAM涉及到的坐标系包括:世界坐标系、相机坐标系、图像坐标系、像素坐标系等。 相机的基本原理是针孔相机模型,什么是针孔相机模型? > 物体发出的光线,经过小孔或透镜后,在密封箱的聚焦屏上生成倒立的实像。极小的孔使得物体各点的光只能到达各自的像点,而不重叠,从而获得清晰的像。针孔越小,通过针孔的光线就越少,像的亮度也就越低。因为是应用了小孔成像的原理所以为光的直线传播。 ![](https://cf02.ickimg.com/bbsimages/202004/11a05857da8e31744fc58d36896d02f7.png) 光沿直线传播,物体在光的反射下通过小孔在底片上呈现出倒影,这是我们在初中物理实验就有的小孔成像原理,相机的基础原理也是如此。 为什么镜头的镜片是凸透镜呢? ![](https://cf02.ickimg.com/bbsimages/202004/920dc5eabe64329cbaa072c4763f95cc.png) 其实也很简单,凸透镜可以汇集更多的光线,让世界坐标系中的物体更多的成像到底片中去。 由上一章的内容可知,世界坐标系的一点为三维坐标,但是在相机坐标系下,我们的成像效果是平面的,所以为二维坐标系。从三维坐标系到二维坐标系下的转换为一个转换矩阵,我们可以理解为这一个转换矩阵就是相机的内参数。 通常情况下,相机的内参数是由厂商提供的,但有时,相机会产生一些畸变,导致我们不得不对相机进行标定,计算出我们需要的内参数。 ## 2.畸变 上述说明,凸透镜的使用可以让更多的光线进入到相机中,但也会产生更多的光线畸变,这种畸变大多数为径向畸变,越向透镜边缘移动径向畸变越严重。 ![](https://cf02.ickimg.com/bbsimages/202004/7d0832d269114fd3447a8b01a8cb1eb4.png) 通常对相机标定的办法有很多种,比如张氏标定法,但是当前各大厂商为了保留自己的商业秘密,大多数没有公开标定的方法,关于张氏标定法,是一个经典的标定法实例,大家感兴趣的可以去看看他的具体数学推算。 > 「张氏标定法」是张正友博士在1999年发表在国际顶级会议ICCV上的论文《Flexible Camera Calibration By Viewing a Plane From Unknown Orientations》中,提出的一种利用平面棋盘格进行相机标定的实用方法。该方法介于摄影标定法和自标定法之间,既克服了摄影标定法需要的高精度三维标定物的缺点,又解决了自标定法鲁棒性差的难题。标定过程仅需使用一个打印出来的棋盘格,并从不同方向拍摄几组图片即可,任何人都可以自己制作标定图案,不仅实用灵活方便,而且精度很高,鲁棒性好。因此很快被全世界广泛采用,极大的促进了三维计算机视觉从实验室走向真实世界的进程。 ![](https://cf02.ickimg.com/bbsimages/202004/c800ecf2e3272b88561f4b72529edb8a.png) # 二、图像 ## 1.双目相机 双目相机和原理形象的来说和人的双眼相似,人的双眼可感知外界环境。双目相机相比单目相机可以说多了一个深度信息,关于双目相机的立体匹配,我会单开一章介绍,这是一个复杂的计算过程,也有很多研究领域聚焦于此,当然,作为一款视觉SLAM问题中尤为重要的一款硬件,还是希望大家可以去了解一些他的原理。 ![](https://cf02.ickimg.com/bbsimages/202004/a7cf895e6f1ab3cecc76ffe14e5e2b13.png) ## 2.深度相机 深度相机,也称RGBD相机,他的原理和雷达类似,主动发送光线然后通过感知返回的光线,主动感知外界的深度,这一点和双目相机不同,双目相机是一个被动感知的过程,而深度相机是一个主动感知的过程,与雷达相比,深度相机的成本更低。 ![](https://cf02.ickimg.com/bbsimages/202004/0843aec65182b78260a7a63d440db153.png) ## 3.图像 > 图像是人类视觉的基础,是自然景物的客观反映,是人类认识世界和人类本身的重要源泉。“图”是物体反射或透射光的分布,“像“是人的视觉系统所接受的图在人脑中所形版的印象或认识,照片、绘画、剪贴画、地图、书法作品、手写汉学、传真、卫星云图、影视画面、X光片、脑电图、心电图等都是图像。 当把世界中三维信息转换为相机的二维信息后就得出了我们的图像,图像是研究视觉的基础,是视觉SLAM中基本的构成元素。通常情况下,图像的信息为RGB,当然,也有很多其他的定义,这里就按照最常见的RGB图像进行说明。 图像是由像素构成的,一系列像素构成了图像,而在传统的SLAM问题中,也是在像素层面展开计算和讨论,当然,现在也有了更加新颖的技术,这块我会在后面的进阶课程讲解。 # 三、实践 这里,我们使用OpenCV作为我们演示程序的库,关于其的安装,网上有大量资源,这里就不做过多介绍,甚至在一些LINUX平台已经安装好了OpenCV库。 ```cpp #include
#include
using namespace std; #include
#include
int main(int argc, char **argv) { // 读取argv[1]指定的图像 cv::Mat image; image = cv::imread(argv[1]); //cv::imread函数读取指定路径下的图像 // 判断图像文件是否正确读取 if (image.data == nullptr) { //数据不存在,可能是文件不存在 cerr << "文件" << argv[1] << "不存在." << endl; return 0; } // 文件顺利读取, 首先输出一些基本信息 cout << "图像宽为" << image.cols << ",高为" << image.rows << ",通道数为" << image.channels() << endl; cv::imshow("image", image); // 用cv::imshow显示图像 cv::waitKey(0); // 暂停程序,等待一个按键输入 // 判断image的类型 if (image.type() != CV_8UC1 && image.type() != CV_8UC3) { // 图像类型不符合要求 cout << "请输入一张彩色图或灰度图." << endl; return 0; } // 遍历图像, 请注意以下遍历方式亦可使用于随机像素访问 // 使用 std::chrono 来给算法计时 chrono::steady_clock::time_point t1 = chrono::steady_clock::now(); for (size_t y = 0; y < image.rows; y++) { // 用cv::Mat::ptr获得图像的行指针 unsigned char *row_ptr = image.ptr
(y); // row_ptr是第y行的头指针 for (size_t x = 0; x < image.cols; x++) { // 访问位于 x,y 处的像素 unsigned char *data_ptr = &row_ptr[x * image.channels()]; // data_ptr 指向待访问的像素数据 // 输出该像素的每个通道,如果是灰度图就只有一个通道 for (int c = 0; c != image.channels(); c++) { unsigned char data = data_ptr[c]; // data为I(x,y)第c个通道的值 } } } chrono::steady_clock::time_point t2 = chrono::steady_clock::now(); chrono::duration
time_used = chrono::duration_cast < chrono::duration < double >> (t2 - t1); cout << "遍历图像用时:" << time_used.count() << " 秒。" << endl; // 关于 cv::Mat 的拷贝 // 直接赋值并不会拷贝数据 cv::Mat image_another = image; // 修改 image_another 会导致 image 发生变化 image_another(cv::Rect(0, 0, 100, 100)).setTo(0); // 将左上角100*100的块置零 cv::imshow("image", image); cv::waitKey(0); // 使用clone函数来拷贝数据 cv::Mat image_clone = image.clone(); image_clone(cv::Rect(0, 0, 100, 100)).setTo(255); cv::imshow("image", image); cv::imshow("image_clone", image_clone); cv::waitKey(0); // 对于图像还有很多基本的操作,如剪切,旋转,缩放等,限于篇幅就不一一介绍了,请参看OpenCV官方文档查询每个函数的调用方法. cv::destroyAllWindows(); return 0; } ``` # 小结 这里,我们就介绍完了相机和原理和图像基础,通过显示程序,相信大家也对OpenCV这个视觉库有所了解,接下来,我们会进入到SLAM中关键问题的解决,非线性优化部分,这是SLAM中的难点,我会尽量简单介绍这部分,以便让大家有所入门。
原创作品,未经权利人授权禁止转载。详情见
转载须知
。
举报文章
点赞
(
0
)
hero_chao
关注
评论
(0)
登录后可评论,请
登录
或
注册
相关文章推荐
MK-米客方德推出工业级存储卡
Beetle ESP32 C3 蓝牙数据收发
Beetle ESP32 C3 wifi联网获取实时天气信息
开箱测评Beetle ESP32-C3 (RISC-V芯片)模块
正点原子数控电源DP100测评
DP100试用评测-----开箱+初体验
Beetle ESP32 C3环境搭建
【花雕体验】16 使用Beetle ESP32 C3控制8X32位WS2812硬屏之二
X
你的打赏是对原创作者最大的认可
请选择打赏IC币的数量,一经提交无法退回 !
100IC币
500IC币
1000IC币
自定义
IC币
确定
X
提交成功 ! 谢谢您的支持
返回
我要举报该内容理由
×
广告及垃圾信息
抄袭或未经授权
其它举报理由
请输入您举报的理由(50字以内)
取消
提交