深度相机原理揭秘--双目立体视觉
双目相机空间坐标计算:(good)
https://www.cnblogs.com/zyly/p/9373991.html
深度相机原理:
https://blog.youkuaiyun.com/electech6/article/details/78526800
上文的博客总结双目相机和单目相机的区别和原理很好,值得学习。
在这里我总结一下主要是以下几点:
深度相机主要有一下几种:
- 基于TOF(time of flight)飞行时间测距法--发射反射接收
- 基于结构光:结构光成像的硬件:1.相机、2.投射器。 原理:1.投射到被测物体表面 2.由单个或多个相机拍摄表面即得的结构光 3.基于三角测量原理,经图像三维解析计算--》三维重建 常见的仪器:kinect
- 基于双目的立体视觉
我们主要总结下双目立体视觉:
在单目的视野A情况下,点的远近是看不出的,加上视野B我们就可以看出
而通过相机A、B我们就可以判断三点的远近
在Opencv中我们可以很好的实现双目相机的标定等一系列操作:
- 分别校正左相机和右相机,得到他们的内参和畸变系数
- 找到左右标定图的内角点坐标,加上三维的世界坐标,加上上面的左右相机内参矩阵和畸变系数,求出双目的标定参数矩阵R、T、E、F(旋转矩阵、平移矩阵、本征矩阵、基础矩阵)
- 根据上面的标定结果,对图像进行矫正--------极线约束,矫正后两图像位于同一平面且互相平行
- 对矫正后的两张图像进行像素匹配(有很多算法),获得视差图,计算每个图像的深度,获得深度图
左右棋盘图如下:
在Opencv中的代码如下,有详细的注释:
main.cpp
#include"11.h"
int main()
{
calibrator calib(LEFT_FOLDER, RIGHT_FOLDER, 1.f, 5, 4);
calib.calc_image_points(true); //找到左右标定图的角点坐标
bool done = calib.calibrate(); //双目标定计算,并保存stereo_calib.xml,得到 R, T, E, F
// R– 输出第一和第二相机坐标系之间的旋转矩阵。
// T– 输出第一和第二相机坐标系之间的旋转矩阵平移向量。
// E–输出本征矩阵。
// F–输出基础矩阵。
if (!done)
{
cout << "立体标定失败......." << endl;
}
else
{
cout << "立体标定成功......." << endl;
}
Size image_size(320, 240);
rectifier rec(filename11, image_size);//标定过的摄像机进行校正,stereoRectify(),得到 Rl, Rr, Pl, Pr, Q
//R1– 输出第一个相机的3x3矫正变换(旋转矩阵) .
//R2– 输出第二个相机的3x3矫正变换(旋转矩阵) .
//P1–在第一台相机的新的坐标系统(矫正过的)输出 3x4 的投影矩阵
//P2–在第二台相机的新的坐标系统(矫正过的)输出 3x4 的投影矩阵
//Q–输出深度视差映射矩阵
rec.show_rectified(image_size);
disparity disp(filename11, image_size); //SGBM求视差图,进而求解深度图
disp.show_disparity(image_size);
system("pause");
return 0;
}
11.h
#pragma once
// Program illustrate stereo camera calibration
// Author: Samarth Manoj Brahmbhatt, University of Pennsylvania
#include <opencv2/opencv.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/calib3d/calib3d.hpp>
#define LEFT_FOLDER "./left/"
#define RIGHT_FOLDER "./right/"
#define DATA_FOLDER "./cam_calib/"
#define filename11 "./cam_calib/stereo_calib.xml"
using namespace cv;
using namespace std;
class calibrator
{
public:
calibrator(string, string, float, int, int); //初始化构造函数
Size get_image_size(); //获取单张图片的大小
void calc_image_points(bool); //通过检测棋盘格角点计算图像点
//得到 l_image_points, r_image_points
bool calibrate();