视差转深度公式如下
depth=(f*baseline)/disp
下面截图自李迎松的立体匹配理论与实战公开课,B站有
深度公式2是深度公式1的特殊形式
对深度公式进行了推导,推导不难,利用相似三角形原理。
实际写视差图转深度图的代码时,必然要严格确认每个变量的单位。
视差转深度公式depth=(f*baseline)/disp里面的单位,现在都可以严格确定下来,depth是毫米,baselline也是毫米,disp是像素,f则是mm/像素的单位,都对的上正好!!!!而且深度图是16UC1(我看到的视差图转深度图函数用的深度图对应的变量类型就是16UC1,以及D435i的深度图也是16UC1),也就是最大表示2的16次方65536的距离,对应单位正好是毫米,也就是65米左右的距离,对深度图而言这个范围正好够了,650米和6.5米都不合适,所以深度图的像素值代表的深度单位就是毫米。 我再说下公式里的f,不是焦距,标定参数里的f是焦距/d,这个d是像元尺寸,也就是一个像素真正长宽多少毫米,这个是像素到毫米单位转化的关键,所以也才能吧像素为单位的视差图转为真实长度为单位的深度图!
视差图转深度图参考代码,摘自下面博客
https://blog.csdn.net/qq_36955294/article/details/84140788
/*
函数作用:视差图转深度图
输入:
dispMap ----视差图,8位单通道,CV_8UC1
K ----内参矩阵,float类型
输出:
depthMap ----深度图,16位无符号单通道,CV_16UC1
*/
void disp2Depth(cv::Mat dispMap, cv::Mat &depthMap, cv::Mat K)
{
int type = dispMap.type();
float fx = K.at<float>(0, 0);
float fy = K.at<float>(1, 1);
float cx = K.at<float>(0, 2);
float cy = K.at<float>(1, 2);
float baseline = 65; //基线距离65mm
if (type == CV_8U)
{
const float PI = 3.14159265358;
int height = dispMap.rows;
int width = dispMap.cols;
uchar* dispData = (uchar*)dispMap.data;
ushort* depthData = (ushort*)depthMap.data;
for (int i = 0; i < height; i++)
{
for (int j = 0; j < width; j++)
{
int id = i*width + j;
if (!dispData[id]) continue; //防止0除
depthData[id] = ushort( (float)fx *baseline / ((float)dispData[id]) );
}
}
}
else
{
cout << "please confirm dispImg's type!" << endl;
cv::waitKey(0);
}
}