2012-11-19 61 views
1

我有一些代碼可以計算出cv :: stereoRectifyUncalibrated計算值的所有部分。但是,我不確定該從哪裏去從中獲取3D點雲。OpenCV StereoRectify未校準到3D點雲

我的代碼與校準版本一起工作,給我一個Q矩陣,然後用reprojectImageTo3D和StereoBM給我一個點雲。

我想比較兩種不同方法的結果,因爲有時我無法校準相機。

回答

0

http://blog.martinperis.com/2012/01/3d-reconstruction-with-opencv-and-point.html我認爲這會有所幫助。它具有使用PCL將視差圖轉換爲點雲的代碼,並在3D查看器中顯示。

由於您有Q,兩個圖像和其他相機參數(來自校準),您應該使用ReprojectTo3D來獲取深度圖。

使用StereoBMstereoSGBM來獲得視差圖並使用該差異圖和Q來獲得深度圖像。

StereoBM sbm; 
sbm.state->SADWindowSize = 9; 
sbm.state->numberOfDisparities = 112; 
sbm.state->preFilterSize = 5; 
sbm.state->preFilterCap = 61; 
sbm.state->minDisparity = -39; 
sbm.state->textureThreshold = 507; 
sbm.state->uniquenessRatio = 0; 
sbm.state->speckleWindowSize = 0; 
sbm.state->speckleRange = 8; 
sbm.state->disp12MaxDiff = 1; 

sbm(g1, g2, disp); // g1 and g2 are two gray images 
reprojectImageTo3D(disp, Image3D, Q, true, CV_32F); 

該代碼基本上將深度圖轉換爲點雲。

pcl::PointCloud<pcl::PointXYZRGB>::Ptr point_cloud_ptr (new pcl::PointCloud<pcl::PointXYZRGB>); 
double px, py, pz; 
uchar pr, pg, pb; 

for (int i = 0; i < img_rgb.rows; i++) 
{ 
    uchar* rgb_ptr = img_rgb.ptr<uchar>(i); 
    uchar* disp_ptr = img_disparity.ptr<uchar>(i); 
    double* recons_ptr = recons3D.ptr<double>(i); 
    for (int j = 0; j < img_rgb.cols; j++) 
    { 
     //Get 3D coordinates 

      uchar d = disp_ptr[j]; 
      if (d == 0) continue; //Discard bad pixels 
      double pw = -1.0 * static_cast<double>(d) * Q32 + Q33; 
      px = static_cast<double>(j) + Q03; 
      py = static_cast<double>(i) + Q13; 
      pz = Q23; 

      // Normalize the points 
      px = px/pw; 
      py = py/pw; 
      pz = pz/pw; 

      //Get RGB info 
      pb = rgb_ptr[3*j]; 
      pg = rgb_ptr[3*j+1]; 
      pr = rgb_ptr[3*j+2]; 

      //Insert info into point cloud structure 
      pcl::PointXYZRGB point; 
      point.x = px; 
      point.y = py; 
      point.z = pz; 
      uint32_t rgb = (static_cast<uint32_t>(pr) << 16 | 
      static_cast<uint32_t>(pg) << 8 | static_cast<uint32_t>(pb)); 
      point.rgb = *reinterpret_cast<float*>(&rgb); 
      point_cloud_ptr->points.push_back (point); 
    } 
} 

point_cloud_ptr->width = (int) point_cloud_ptr->points.size(); 
point_cloud_ptr->height = 1; 

//Create visualizer 
boost::shared_ptr<pcl::visualization::PCLVisualizer> viewer; 
viewer = createVisualizer(point_cloud_ptr); 
+0

雖然這可能理論上回答這個問題,[這將是優選的](http://meta.stackexchange.com/q/8259),包括在這裏的答案的主要部分,並且提供的鏈接參考。 – Taryn

+0

實際上,該鏈接具有將OpenCV視差圖轉換爲PCL點雲並以3D顯示的代碼。 – Froyo

+0

問題是你只給了一個鏈接,如果鏈接失敗,這個答案將會過時。您應該在這裏提供鏈接,代碼等的概述,並僅包含鏈接作爲參考。 – Taryn