使用后置滤波的立体地图

时间:2017-11-21 04:51:35

标签: opencv computer-vision stereo-3d 3d-reconstruction disparity-mapping

我尝试使用代码来查找链接中给出的差异:link但是视差图在某些区域似乎是错误的。远离相机的一些物体看起来比较近的物体更亮。我试图通过将视差值乘以校准矩阵Q来计算实际深度。计算的深度与实际测量值(偏离20-25cm)相差不大。我确信矩阵Q是正确的,因为我纠正的图像看起来很好。我校准的方形尺寸值也是准确的(0.05米)。我的差异图像附有:
enter image description here

这是用于根据存储在filtered_disp_vis中的滤波视差图像计算实际深度的附加代码。

fs1["Q"] >> Q;
Mat Image;
Mat V = Mat(4, 1, CV_64FC1);
Mat pos = Mat(4, 1, CV_64FC1);
vector< Point3d > points;
//float fMaxDistance = static_cast<float>((1. / Q.at<double>(3, 2)) * 
Q.at<double>(2, 3));
//filtered_disp_vis.convertTo(filtered_disp_vis, CV_64FC1, 1.0 / 16.0, 0.0);
//imshow("filtered disparity", filtered_disp_vis);
// outputDisparityValue is single 16-bit value from disparityMap
// DISP_SCALE = 16
//float fDisparity = outputDisparityValue / 
(float)StereoMatcher::DISP_SCALE;
//float fDistance = fMaxDistance / fDisparity;
reprojectImageTo3D(filtered_disp_vis, Image, Q, false, CV_32F);
//cout << Image;
for (int i = 0; i < filtered_disp_vis.cols; i++)
{
for (int j = 0; j < filtered_disp_vis.rows; j++)
{
int d = filtered_disp_vis.at<uchar>(j, i);
//filtered_disp_vis.convertTo(filtered_disp_vis, CV_32F, 1.0 / 16.0, 0.0);
//int l = img_left.at<uchar>(j, i);
//cout << "(" << j << "," << i << ")" << "=" << d;
//out << endl;
// if low disparity, then ignore
/*if (d < 2) {
continue;
}*/
// V is the vector to be multiplied to Q to get
// the 3D homogenous coordinates of the image point
V.at<double>(0, 0) = (double)(i);
V.at<double>(1, 0) = (double)(j);
V.at<double>(2, 0) = (double)d;
V.at<double>(3, 0) = 1.;
pos = Q * V; // 3D homogeneous coordinate
double X = pos.at<double>(0, 0) / pos.at<double>(3, 0);
double Y = pos.at<double>(1, 0) / pos.at<double>(3, 0);
double Z = pos.at<double>(2, 0) / pos.at<double>(3, 0);

if (i == 446 && j == 362)
{
cout << "(" << j << "," << i << ")" << " =   ";

cout << X << " " << Y << " " << Z << " " << d;
cout << endl;
}

Mat point3d_cam = Mat(3, 1, CV_64FC1);
point3d_cam.at<double>(0, 0) = X;
point3d_cam.at<double>(1, 0) = Y;
point3d_cam.at<double>(2, 0) = Z;
// transform 3D point from camera frame to robot frame
//Mat point3d_robot = XR * point3d_cam + XT;
points.push_back(Point3d(point3d_cam));
}

我哪里错了?我的片段的任何修改或不同的建议,以获得具有准确深度值的正确视差图将是值得赞赏的。

1 个答案:

答案 0 :(得分:0)

我还无法在您的问题中添加评论(因为信誉最低)。所以我会在这里发表评论:

1 - 您是否尝试仅使用KITTI数据集中的一对帧进行后置过滤?如果是这样,结果是否也会变坏?

2 - 如果KITTI数据集没问题,那么校准可能会出现问题。在进行立体声校准和校正之后,您是否正在应用undistort(两个相机校准)?

* undistort

第二部分(我试图将其作为回应你的评论,但我对评论字段的反应太大了......)= P

对于延迟感到抱歉,过去几天我很忙。所以,让我们分一部分:

1)我使用了filtered_disp_vis。

2)如果KITTI没问题,那么问题可能在于您的相机或整改。你用的是哪种相机?你的相机是否静止不动?

2.1)我曾经使用简单的网络摄像头(滚动快门系统),但大多数时候结果看起来很糟糕。立体视觉的理想选择是具有全局快门系统的摄像机。

3)对于我使用的不同颜色&#34; applyColorMap&#34;来自OpenCV。

第三部分(太久了):

a)好吧,看起来这个相机传感器是滚动快门,但我不确定......可以工作,但如果你想继续移动你的相机你就会遇到问题。 在校准过程中尽量不要拿着相机,试着放在表面上让它停下来。这里有关于校准的很好的提示:camera calibration

b) 它不是实时的,但它可以像CPU一样快。我只是用VideoCapture拍摄帧,当帧不断出现时,我移动到了#34;内部的cv :: Mat;而#34;循环。

cv::Mat imgOne, imgTwo;

VideoCapture videoOne("path/To/The/Frames/%10d.png");
VideoCapture videoTwo("path/To/The/FramesTwo/%10d.png");

while(1){
    videoOne >> imgOne;
    videoTwo >> imgTwo;

    //rest of code.
}

c)我没有进行3D重建。

d)使用Vec3b获取一个位置,并使用uchar在每个通道中获取值。我没有进行任何额外的转换。