Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/opencv/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Opencv,计算从深度矩阵到像素的距离_Opencv_Computer Vision - Fatal编程技术网

Opencv,计算从深度矩阵到像素的距离

Opencv,计算从深度矩阵到像素的距离,opencv,computer-vision,Opencv,Computer Vision,我有一个视差图像创建与校准立体相机对和opencv。看起来不错,我的校准数据也不错 我需要计算一个像素的真实距离 从stackoverflow的其他问题中,我看到了以下方法: 深度=基线*焦点/视差 使用该功能: setMouseCallback("disparity", onMouse, &disp); static void onMouse(int event, int x, int y, int flags, void* param) { cv::Mat &xy

我有一个视差图像创建与校准立体相机对和opencv。看起来不错,我的校准数据也不错

我需要计算一个像素的真实距离

从stackoverflow的其他问题中,我看到了以下方法:

深度=基线*焦点/视差

使用该功能:

setMouseCallback("disparity", onMouse, &disp); 

static void onMouse(int event, int x, int y, int flags, void* param)
{
    cv::Mat &xyz = *((cv::Mat*)param); //cast and deref the param
    if (event == cv::EVENT_LBUTTONDOWN)
    {
        unsigned int val = xyz.at<uchar>(y, x);

        double depth = (camera_matrixL.at<float>(0, 0)*T.at<float>(0, 0)) / val;

        cout << "x= " << x << " y= " << y << " val= " << val << " distance: " << depth<< endl;
    }
}
这给了我一个距离(如果我们假设为毫米单位,则更接近事实)
val=31距离:2281.27
但这仍然是错误的

以下哪种方法是正确的?我哪里做错了

左,右,深度图。(编辑:此深度贴图来自不同的一对图像)

编辑:根据答案,我正在尝试以下方法:

`矢量点云

float fx = 284.492615;
float fy = 285.683197;
float cx = 424;// 425.807709;
float cy = 400;// 395.494293;

cv::Mat Q = cv::Mat(4,4, CV_32F);
Q.at<float>(0, 0) = 1.0;
Q.at<float>(0, 1) = 0.0;
Q.at<float>(0, 2) = 0.0;
Q.at<float>(0, 3) = -cx; //cx
Q.at<float>(1, 0) = 0.0;
Q.at<float>(1, 1) = 1.0;
Q.at<float>(1, 2) = 0.0;
Q.at<float>(1, 3) = -cy;  //cy
Q.at<float>(2, 0) = 0.0;
Q.at<float>(2, 1) = 0.0;
Q.at<float>(2, 2) = 0.0;
Q.at<float>(2, 3) = -fx;  //Focal
Q.at<float>(3, 0) = 0.0;
Q.at<float>(3, 1) = 0.0;
Q.at<float>(3, 2) = -1.0 / 6;    //1.0/BaseLine
Q.at<float>(3, 3) = 0.0;    //cx - cx'

//
cv::Mat XYZcv(depth_image.size(), CV_32FC3);
reprojectImageTo3D(depth_image, XYZcv, Q, false, CV_32F);

for (int y = 0; y < XYZcv.rows; y++)
{
    for (int x = 0; x < XYZcv.cols; x++)
    {
        cv::Point3f pointOcv = XYZcv.at<cv::Point3f>(y, x);

        Eigen::Vector4d pointEigen(0, 0, 0, left.at<uchar>(y, x) / 255.0);
        pointEigen[0] = pointOcv.x;
        pointEigen[1] = pointOcv.y;
        pointEigen[2] = pointOcv.z;

        pointcloud.push_back(pointEigen);

    }
}`
float fx=284.492615;
浮动fy=285.683197;
浮动cx=424;//425.807709;
浮动cy=400;//395.494293;
cv::Mat Q=cv::Mat(4,4,cv_32F);
Q.at(0,0)=1.0;
Q.at(0,1)=0.0;
Q.at(0,2)=0.0;
Q.at(0,3)=-cx//cx
Q.at(1,0)=0.0;
Q.at(1,1)=1.0;
Q.at(1,2)=0.0;
Q.at(1,3)=-cy//赛义德
Q.at(2,0)=0.0;
Q.at(2,1)=0.0;
Q.at(2,2)=0.0;
Q.at(2,3)=-fx//焦点的
Q.at(3,0)=0.0;
Q.at(3,1)=0.0;
Q.at(3,2)=-1.0/6//1.0/基线
Q.at(3,3)=0.0//cx-cx'
//
cv::Mat XYZcv(depth_image.size(),cv_32FC3);
重新投影到3D(深度图像,XYZcv,Q,假,CV_32F);
对于(int y=0;y

这给了我一个云。

我建议使用OpenCV的
重新投影到3D
来重建与视差的距离。请注意,使用此函数时,您确实必须将立体声GBM的输出除以16。您应该已经拥有了所有参数
f
cx
cy
Tx
。注意用相同的单位表示f和Tx。cx、cy以像素为单位。 因为问题是你需要Q矩阵,我认为它应该帮助你建立它。如果您不想使用
reprojectmageto3d
我强烈推荐第一个链接


我希望这有帮助

要从摄影机中查找对象的基于点的深度,请使用以下公式:

深度=(基线x焦距)/视差

我希望你根据你的问题正确地使用它

请尝试下面的nerian计算器查找理论错误

另外,在代码中使用亚像素插值

确保要确定深度的对象应有良好的纹理

深度贴图最常见的问题是:

  • 无结构曲面(普通对象)
  • 校准结果不好
  • 校准、相机分辨率和镜头类型(焦距)的RMS值是多少
    长度)?这对于为您的程序提供更好的数据非常重要。

    几个问题:您是如何估计校准是否良好的?你用了多少张图片?您是否使用立体GBM进行视差估计?你能提供校正后的图像和深度图吗?为什么不使用ReprojectMageto3D重新映射所有点?为什么立体声基线以米为单位,而你期望毫米?一句话:fMaxDistance是错误的(括号!),如果你将差距除以16,你应该得到0.590693*16。嗨,谢谢你的回答。校准矩阵是根据立体摄像机的车载校准数据创建的(出厂校准)。我确实使用了
    立体GBM
    ,然后使用
    DisparityWLSFilter
    。我不使用ReprojectMageto3D,因为我已经手动创建了矩阵,所以我没有
    Q
    矩阵。深度贴图代码主要基于以下内容:“我将添加一些图像。谢谢!我正在使用
    重新投影到3D
    ,(问题中添加了代码),我得到了一个非常好的云。这种方法正确吗?我是否需要
    depth\u image.convertTo(depth\u image,CV\u 32F,1./16)?。。但是,深度值看起来仍然不正确。4米的距离显示为1.3米,云层看起来被压扁了。我不确定Tx,它应该是0.6而不是6,对吗?实际上,顶部的变量(如fx)会更好。那么,cx和cx’是否相同(对于(3,3)处的值Q)?在我的例子中,焦距是正的。我认为如果你使用立体GBM,你需要在某一点上把视差除以16。在一些示例中,它们执行imgDisparity16S.convertTo(imgDisparity32F,CV_32F,1./16);实际上,如果你想把所有的东西都放在毫米上,Tx应该是60。我不知道你们的外汇单位,fy。
    cx-cx'
    是什么意思?什么是
    cx'
    值?
    float fx = 284.492615;
    float fy = 285.683197;
    float cx = 424;// 425.807709;
    float cy = 400;// 395.494293;
    
    cv::Mat Q = cv::Mat(4,4, CV_32F);
    Q.at<float>(0, 0) = 1.0;
    Q.at<float>(0, 1) = 0.0;
    Q.at<float>(0, 2) = 0.0;
    Q.at<float>(0, 3) = -cx; //cx
    Q.at<float>(1, 0) = 0.0;
    Q.at<float>(1, 1) = 1.0;
    Q.at<float>(1, 2) = 0.0;
    Q.at<float>(1, 3) = -cy;  //cy
    Q.at<float>(2, 0) = 0.0;
    Q.at<float>(2, 1) = 0.0;
    Q.at<float>(2, 2) = 0.0;
    Q.at<float>(2, 3) = -fx;  //Focal
    Q.at<float>(3, 0) = 0.0;
    Q.at<float>(3, 1) = 0.0;
    Q.at<float>(3, 2) = -1.0 / 6;    //1.0/BaseLine
    Q.at<float>(3, 3) = 0.0;    //cx - cx'
    
    //
    cv::Mat XYZcv(depth_image.size(), CV_32FC3);
    reprojectImageTo3D(depth_image, XYZcv, Q, false, CV_32F);
    
    for (int y = 0; y < XYZcv.rows; y++)
    {
        for (int x = 0; x < XYZcv.cols; x++)
        {
            cv::Point3f pointOcv = XYZcv.at<cv::Point3f>(y, x);
    
            Eigen::Vector4d pointEigen(0, 0, 0, left.at<uchar>(y, x) / 255.0);
            pointEigen[0] = pointOcv.x;
            pointEigen[1] = pointOcv.y;
            pointEigen[2] = pointOcv.z;
    
            pointcloud.push_back(pointEigen);
    
        }
    }`