Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/136.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

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
C++ 在OpenCV中重新投影Mageto3D()_C++_Opencv - Fatal编程技术网

C++ 在OpenCV中重新投影Mageto3D()

C++ 在OpenCV中重新投影Mageto3D(),c++,opencv,C++,Opencv,我一直在尝试使用OpenCV提供的reprojectMageto3D()函数从视差图计算点的真实坐标,但输出似乎不正确 我有校准参数,并使用 立体校正(左视距矩阵、左视距系数、右视距矩阵、右视距系数、帧大小、立体参数R、立体参数T、R1、R2、P1、P2、Q、校准零视差、0、帧大小、0、0、0) 我相信这第一步是正确的,因为立体声帧被正确地校正了,我正在执行的失真消除看起来也不错。视差图是用OpenCV的块匹配算法计算的,看起来也不错 三维点的计算如下所示: cv::Mat XYZ(dispar

我一直在尝试使用OpenCV提供的reprojectMageto3D()函数从视差图计算点的真实坐标,但输出似乎不正确

我有校准参数,并使用

立体校正(左视距矩阵、左视距系数、右视距矩阵、右视距系数、帧大小、立体参数R、立体参数T、R1、R2、P1、P2、Q、校准零视差、0、帧大小、0、0、0)

我相信这第一步是正确的,因为立体声帧被正确地校正了,我正在执行的失真消除看起来也不错。视差图是用OpenCV的块匹配算法计算的,看起来也不错

三维点的计算如下所示:

cv::Mat XYZ(disparity8U.size(),cv_32FC3);
重新投影到3D(不均匀8U、XYZ、Q、false、CV_32F)

但出于某种原因,它们形成了某种圆锥体,考虑到视差图,它们甚至不接近我所期望的。我发现其他人对此函数也有类似的问题,我想知道是否有人有解决方案

提前谢谢

[编辑]

stereoRectify(left_cam_matrix, left_dist_coeffs, right_cam_matrix, right_dist_coeffs,frame_size, stereo_params.R, stereo_params.T, R1, R2, P1, P2, Q, CALIB_ZERO_DISPARITY, 0, frame_size, 0, 0);

initUndistortRectifyMap(left_cam_matrix, left_dist_coeffs, R1, P1, frame_size,CV_32FC1, left_undist_rect_map_x, left_undist_rect_map_y);
initUndistortRectifyMap(right_cam_matrix, right_dist_coeffs, R2, P2, frame_size, CV_32FC1, right_undist_rect_map_x, right_undist_rect_map_y);
cv::remap(left_frame, left_undist_rect, left_undist_rect_map_x, left_undist_rect_map_y, CV_INTER_CUBIC, BORDER_CONSTANT, 0);
cv::remap(right_frame, right_undist_rect, right_undist_rect_map_x, right_undist_rect_map_y, CV_INTER_CUBIC, BORDER_CONSTANT, 0);

cv::Mat imgDisparity32F = Mat( left_undist_rect.rows, left_undist_rect.cols, CV_32F );  
StereoBM sbm(StereoBM::BASIC_PRESET,80,5);
sbm.state->preFilterSize  = 15;
sbm.state->preFilterCap   = 20;
sbm.state->SADWindowSize  = 11;
sbm.state->minDisparity   = 0;
sbm.state->numberOfDisparities = 80;
sbm.state->textureThreshold = 0;
sbm.state->uniquenessRatio = 8;
sbm.state->speckleWindowSize = 0;
sbm.state->speckleRange = 0;

// Compute disparity
sbm(left_undist_rect, right_undist_rect, imgDisparity32F, CV_32F );

// Compute world coordinates from the disparity image
cv::Mat XYZ(disparity32F.size(),CV_32FC3);
reprojectImageTo3D(disparity32F, XYZ, Q, false, CV_32F);
print_3D_points(disparity32F, XYZ);
[编辑]

stereoRectify(left_cam_matrix, left_dist_coeffs, right_cam_matrix, right_dist_coeffs,frame_size, stereo_params.R, stereo_params.T, R1, R2, P1, P2, Q, CALIB_ZERO_DISPARITY, 0, frame_size, 0, 0);

initUndistortRectifyMap(left_cam_matrix, left_dist_coeffs, R1, P1, frame_size,CV_32FC1, left_undist_rect_map_x, left_undist_rect_map_y);
initUndistortRectifyMap(right_cam_matrix, right_dist_coeffs, R2, P2, frame_size, CV_32FC1, right_undist_rect_map_x, right_undist_rect_map_y);
cv::remap(left_frame, left_undist_rect, left_undist_rect_map_x, left_undist_rect_map_y, CV_INTER_CUBIC, BORDER_CONSTANT, 0);
cv::remap(right_frame, right_undist_rect, right_undist_rect_map_x, right_undist_rect_map_y, CV_INTER_CUBIC, BORDER_CONSTANT, 0);

cv::Mat imgDisparity32F = Mat( left_undist_rect.rows, left_undist_rect.cols, CV_32F );  
StereoBM sbm(StereoBM::BASIC_PRESET,80,5);
sbm.state->preFilterSize  = 15;
sbm.state->preFilterCap   = 20;
sbm.state->SADWindowSize  = 11;
sbm.state->minDisparity   = 0;
sbm.state->numberOfDisparities = 80;
sbm.state->textureThreshold = 0;
sbm.state->uniquenessRatio = 8;
sbm.state->speckleWindowSize = 0;
sbm.state->speckleRange = 0;

// Compute disparity
sbm(left_undist_rect, right_undist_rect, imgDisparity32F, CV_32F );

// Compute world coordinates from the disparity image
cv::Mat XYZ(disparity32F.size(),CV_32FC3);
reprojectImageTo3D(disparity32F, XYZ, Q, false, CV_32F);
print_3D_points(disparity32F, XYZ);
添加用于从视差计算3D坐标的代码:

cv::Vec3f *StereoFrame::compute_3D_world_coordinates(int row, int col,
  shared_ptr<StereoParameters> stereo_params_sptr){

 cv::Mat Q_32F;

 stereo_params_sptr->Q_sptr->convertTo(Q_32F,CV_32F);
 cv::Mat_<float> vec(4,1);

 vec(0) = col;
 vec(1) = row;
 vec(2) = this->disparity_sptr->at<float>(row,col);

 // Discard points with 0 disparity    
 if(vec(2)==0) return NULL;
 vec(3)=1;              
 vec = Q_32F*vec;
 vec /= vec(3);
 // Discard points that are too far from the camera, and thus are highly
 // unreliable
 if(abs(vec(0))>10 || abs(vec(1))>10 || abs(vec(2))>10) return NULL;

 cv::Vec3f *point3f = new cv::Vec3f();
 (*point3f)[0] = vec(0);
 (*point3f)[1] = vec(1);
 (*point3f)[2] = vec(2);

    return point3f;
}
cv::Vec3f*立体框架::计算三维世界坐标(整数行、整数列、,
共享(ptr立体声参数sptr){
cv::Mat Q_32F;
立体声参数sptr->Q_sptr->convertTo(Q_32F,CV_32F);
cv::Mat_vec(4,1);
vec(0)=col;
vec(1)=行;
vec(2)=此->差异\u sptr->at(行,列);
//丢弃视差为0的点
if(vec(2)==0)返回NULL;
vec(3)=1;
vec=Q_32F*vec;
vec/=vec(3);
//丢弃距离摄影机太远的点,从而使其高度
//不可靠
如果(abs(vec(0))>10 | | abs(vec(1))>10 | | abs(vec(2))>10)返回空值;
cv::Vec3f*point3f=新的cv::Vec3f();
(*点3f)[0]=vec(0);
(*第3f点)[1]=vec(1);
(*第3f点)[2]=vec(2);
返回点3f;
}

我觉得你的代码很好。这可能是一个带有
重新投影到3D
的bug。尝试将其替换为以下代码(具有相同的角色):


您也可以直接从StereoBM结构请求
CV_32F
视差图,在这种情况下,您可以直接获得真实的视差。

您可以显示您获得的视差图以及为立体块匹配算法提供的参数吗?当然,您可以在这里看到左帧和视差:这些是我用来计算视差的参数:StereoBM sbm(StereoBM::BASIC_PRESET,80,5);sbm.state->preFilterSize=15;sbm.state->preFilterCap=20;sbm.state->sadWindowsSize=11;sbm.state->minDisparity=0;sbm.状态->数量差异=80;sbm.state->textureThreshold=0;sbm.state->uniquenessRatio=8;sbm.state->windowsize=0;sbm.状态->范围=0;你说得对,视差图看起来不错。重新投影到3D时的圆锥体形状是否是由于视差图中的噪声造成的?你能展示你在3D中得到的东西吗?嗨,谢谢你迄今为止的帮助!可以在此处看到3D点:。而且,正如我在帖子中所说,有很多人都有着完全相同的问题。这里是他们发布问题()的论坛之一的链接,以防您需要更多的数据。你认为这可能与视差图像的格式有关吗?StereoBM算法返回一个CV_16S图像,我将其转换为CV_8U。这是我如何进行转换的:双minVal;双最大值;minMaxLoc(imgDisparity16S,&minVal,&maxVal);imgDisparity16S.convertTo(imgDisparity8U,CV_8UC1,255/(maxVal-minVal));再次感谢您的快速回复!我尝试使用这两种方法,但结果仍然很奇怪:好的,你能编辑你的帖子并显示你正在使用的代码吗(无论是
stereorective
还是
reprojectmageto3d
)?在花了很多时间和做了很多调整之后,我终于成功地生成了看起来正确的(或者至少是同调的)立体对中的点云。以下是第一个合理结果的屏幕截图:。您可以看到,与图像相比,点似乎发生了翻转,因此我使用了-T而不是T(从校准中获得的平移向量),并得到了以下结果:…[更新]点云上的翻转似乎实际上是PCL visualizer中的一个缺陷(请参阅和)@Daniel Lee我编辑了这个问题,添加了用于从视差图像获取3D坐标的代码(注意,它基于以前的答案,但我添加了一些有效性检查)。我认为您可以轻松地根据自己的需要调整它,并使用它来代替OpenCV的功能。希望有帮助!
imgDisparity16S.convertTo( imgDisparity32F, CV_32F, 1./16);