2015-12-16 4 views
8

Я недавно начал работать с OpenCV 3.0, и моя цель - захватить пару стереоизображений из набора стереокамер, создать правильную карту несоответствия, преобразуйте карту несоответствий в облако 3D-точек и, наконец, покажите полученное облако точек в средстве просмотра облачных точек с помощью PCL.Как создать допустимое представление облачной точки пары стереоизображений с использованием OpenCV 3.0 StereoSGBM и PCL

я уже выполнил калибровку камеры и в результате калибровки RMS составляет 0,4

Вы можете найти свои пары изображений (левое изображение) 1 и (правое изображение) 2 в приведенных ниже ссылок. Я использую StereoSGBM, чтобы создать изображение несоответствия. Я также использую дорожки для настройки параметров функции StereoSGBM, чтобы получить лучшее изображение несоответствия. К сожалению, я не могу опубликовать свое изображение несоответствия, так как я новичок в StackOverflow и не имею достаточной репутации, чтобы размещать более двух ссылок на изображения!

После получения изображения несоответствия («disp» в приведенном ниже коде), я использую функцию repjectImageTo3D() для преобразования информации о несоответствии изображения в координату XYZ 3D, а затем преобразовываю результаты в массив «pcl: : PointXYZRGB ", чтобы они могли отображаться в средстве просмотра облачных точек PCL. После выполнения требуемого преобразования то, что я получаю как облако точек, - это глупое облако точек формы пирамиды, которое не имеет никакого смысла. Я уже прочитал и попробовал все предложенные методы по следующим ссылкам:

1- http: //blog.martinperis.com/2012/01/3d-reconstruction-with-opencv-and-point.html

2- HTTP: //stackoverflow.com/questions/13463476/opencv-stereorectifyuncalibrated-to-3d-point-cloud

3- HTTP: //stackoverflow.com/questions/22418846/reprojectimageto3d-in- opencv

и не из них работали !!!

Ниже я представил часть преобразования моего кода, было бы весьма признателен, если бы вы могли сказать мне, что я пропускаю:

pcl::PointCloud<pcl::PointXYZRGB>::Ptr pointcloud(new pcl::PointCloud<pcl::PointXYZRGB>()); 
    Mat xyz; 
    reprojectImageTo3D(disp, xyz, Q, false, CV_32F); 
    pointcloud->width = static_cast<uint32_t>(disp.cols); 
    pointcloud->height = static_cast<uint32_t>(disp.rows); 
    pointcloud->is_dense = false; 
    pcl::PointXYZRGB point; 
    for (int i = 0; i < disp.rows; ++i) 
     { 
      uchar* rgb_ptr = Frame_RGBRight.ptr<uchar>(i); 
      uchar* disp_ptr = disp.ptr<uchar>(i); 
      double* xyz_ptr = xyz.ptr<double>(i); 

      for (int j = 0; j < disp.cols; ++j) 
      { 
       uchar d = disp_ptr[j]; 
       if (d == 0) continue; 
       Point3f p = xyz.at<Point3f>(i, j); 

       point.z = p.z; // I have also tried p.z/16 
       point.x = p.x; 
       point.y = p.y; 

       point.b = rgb_ptr[3 * j]; 
       point.g = rgb_ptr[3 * j + 1]; 
       point.r = rgb_ptr[3 * j + 2]; 
       pointcloud->points.push_back(point); 
      } 
     } 
    viewer.showCloud(pointcloud); 
+0

уточняйте, пожалуйста, фотографии, которые вы предоставили, они выглядят одинаково – alexisrozhkov

+0

Sorry, My bad. Я загрузил правильные рамки! –

ответ

11

После выполнения некоторых работ и некоторые исследования, я нашел мой ответ, и я разделяя его здесь, чтобы другие читатели могли использовать.

С алгоритмом преобразования от изображения несоответствия до 3D XYZ (и в конечном итоге до облака точек) ничего не получилось. Проблема заключалась в расстоянии объектов (которые я делал снимки) до камер и объеме информации, доступной для алгоритмов StereoBM или StereoSGBM, для обнаружения сходства между двумя изображениями (парой изображений). Чтобы получить правильное облако 3D-точек, требуется наличие хорошего изображения несоответствия и для хорошего изображения несоответствия (при условии, что вы выполнили хорошую калибровку) убедитесь в следующем:

1- Должно быть достаточно обнаруживаемые и отличимые общие функции, доступные между двумя кадрами (правый и левый фреймы). Причина в том, что алгоритмы StereoBM или StereoSGBM ищут общие функции между двумя кадрами, и их можно легко обмануть схожими вещами в двух кадрах, которые могут не обязательно принадлежать тем же объектам. Я лично считаю, что эти два алгоритма соответствия имеют много возможностей для улучшения. Поэтому остерегайтесь того, что вы смотрите на своих камерах.

2 Объекты, представляющие интерес (те, которые вам интересны для их 3D-модели облачных точек), должны находиться на определенном расстоянии от ваших камер. Чем больше базовая линия (базовая линия - это расстояние между двумя камерами), тем дальше могут быть ваши объекты (цели).

Шумовое и искаженное изображение несоответствия никогда не генерирует хорошее облако 3D-точек. Одна вещь, которую вы можете сделать, чтобы улучшить ваши изображения несоответствий, - использовать трек-бары в ваших приложениях, чтобы вы могли настраивать параметры StereoSBM или StereoSGBM, пока не увидите хорошие результаты (четкое и плавное изображение несоответствия). Код ниже - это небольшой и простой пример того, как создавать трек-бары (я написал это как можно проще). Использовать по мере необходимости:

int PreFilterType = 0, PreFilterCap = 0, MinDisparity = 0, UniqnessRatio = 0, TextureThreshold = 0, 
    SpeckleRange = 0, SADWindowSize = 5, SpackleWindowSize = 0, numDisparities = 0, numDisparities2 = 0, PreFilterSize = 5; 


      Ptr<StereoBM> sbm = StereoBM::create(numDisparities, SADWindowSize); 

while(1) 
{ 
      sbm->setPreFilterType(PreFilterType); 
      sbm->setPreFilterSize(PreFilterSize); 
      sbm->setPreFilterCap(PreFilterCap + 1); 
      sbm->setMinDisparity(MinDisparity-100); 
      sbm->setTextureThreshold(TextureThreshold*0.0001); 
      sbm->setSpeckleRange(SpeckleRange); 
      sbm->setSpeckleWindowSize(SpackleWindowSize); 
      sbm->setUniquenessRatio(0.01*UniqnessRatio); 
      sbm->setSmallerBlockSize(15); 
      sbm->setDisp12MaxDiff(32); 

      namedWindow("Track Bar Window", CV_WINDOW_NORMAL); 
      cvCreateTrackbar("Number of Disparities", "Track Bar Window", &PreFilterType, 1, 0); 
      cvCreateTrackbar("Pre Filter Size", "Track Bar Window", &PreFilterSize, 100); 
      cvCreateTrackbar("Pre Filter Cap", "Track Bar Window", &PreFilterCap, 61); 
      cvCreateTrackbar("Minimum Disparity", "Track Bar Window", &MinDisparity, 200); 
      cvCreateTrackbar("Uniqueness Ratio", "Track Bar Window", &UniqnessRatio, 2500); 
      cvCreateTrackbar("Texture Threshold", "Track Bar Window", &TextureThreshold, 10000); 
      cvCreateTrackbar("Speckle Range", "Track Bar Window", &SpeckleRange, 500); 
      cvCreateTrackbar("Block Size", "Track Bar Window", &SADWindowSize, 100); 
      cvCreateTrackbar("Speckle Window Size", "Track Bar Window", &SpackleWindowSize, 200); 
      cvCreateTrackbar("Number of Disparity", "Track Bar Window", &numDisparities, 500); 

      if (PreFilterSize % 2 == 0) 
      { 
       PreFilterSize = PreFilterSize + 1; 
      } 


      if (PreFilterSize2 < 5) 
      { 
       PreFilterSize = 5; 
      } 

      if (SADWindowSize % 2 == 0) 
      { 
       SADWindowSize = SADWindowSize + 1; 
      } 

      if (SADWindowSize < 5) 
      { 
       SADWindowSize = 5; 
      } 


      if (numDisparities % 16 != 0) 
      { 
       numDisparities = numDisparities + (16 - numDisparities % 16); 
      } 
     } 
} 

Если вы не получите правильные результаты и не получите изображение с неравномерностью, не разочаровывайтесь. Попробуйте использовать образцы изображений OpenCV (тот, у которого есть оранжевая настольная лампа) с вашим алгоритмом, чтобы убедиться, что у вас есть правильная линия трубопроводов, а затем попробуйте сделать снимки с разных расстояний и сыграйте с параметрами StereoBM/StereoSGBM, пока вы не сможете получить что-то полезно. Я использовал свое лицо для этой цели, и, поскольку у меня была очень небольшая базовая линия, я очень близко подошел к моим камерам (вот ссылка на мою трехмерную фотографию с изображением лица и эй, не смей смеяться !!!) 1. Я был очень рад видеть себя в форме 3D-облака после недели борьбы. Я никогда не был так счастлив видеть себя раньше !!! ;)