как получить чистую карту несоответствия и чистую ГЛУБОКУЮ КАРТУ - PullRequest
0 голосов
/ 09 мая 2019

В настоящее время я работаю с IP-камерой от Titathink (TT522PW), которая выдает поток 1280 * 720 с 30 FPS с обычными датчиками (не модель с высокой чувствительностью при слабом освещении)

при захвате видеопотока мы видим на кадрах искажение типа «рыбий глаз».

не выпрямленные изображения

non-rectified images

  1. Я впервые откалиброванкаждая камера индивидуально для устранения искажения (при калибровке я получаю среднеквадратичную ошибку левой камеры rms_left = 0,166 и среднеквадратичное значение правой камеры rms_right = 0,162 ).А затем, используя xml-файлы, полученные в результате процесса калибровки отдельных камер, я откалибровал стереокамеры, в стереокалибровке получаю среднеквадратичную ошибку = 0,207

  2. И при отображении калиброванных изображений мы видим, что стереокалибровка была выполнена хорошо

Калиброванные изображения

the calibrated images

Выпрямленное изображение с горизонтальными линиями

rectified image with horizontal lines

Я взял на себя функции dji для расчета карты диспаратности, а также функции для вычисления облака точек

код расчета и фильтрации карты диспаратности

bool Disparity_filter::initDispParam(){


#ifdef USE_CUDA
  block_matcher_ = cv::cuda::createStereoBM(num_disp_, block_size_);
#else
  block_matcher_ = cv::StereoBM::create(num_disp_, block_size_);
#endif

#ifdef USE_OPEN_CV_CONTRIB
  wls_filter_ = cv::ximgproc::createDisparityWLSFilter(block_matcher_); // left_matcher
  wls_filter_->setLambda(8000.0);
  wls_filter_->setSigmaColor(1.5);

  right_matcher_ = cv::ximgproc::createRightMatcher(block_matcher_);
#endif
   return true;
}


void Disparity_filter::computeDisparityMap(std::shared_ptr<Frame> framel, std::shared_ptr<Frame> framer){
framel->raw_disparity_map_=cv::Mat(HEIGHT, WIDTH, CV_16SC1); 
#ifdef USE_CUDA
    cv::cuda::GpuMat cuda_disp_left;
    framel->cuda_crop_left.upload(framel->cpu_crop_left);
    framer->cuda_crop_right.upload(framer->cpu_crop_right);

    // GPU implementation of stereoBM outputs uint8_t, i.e. CV_8U
    block_matcher_->compute(framel->cuda_crop_left.clone(),
                          framer->cuda_crop_right.clone(),
                          cuda_disp_left);
    cuda_disp_left.download(framel->raw_disparity_map_);

    framel->raw_disparity_map_.convertTo(framel->disparity_map_8u_, CV_8UC1, 1);

    // convert it from CV_8U to CV_16U for unified
    // calculation in filterDisparityMap() & unprojectPtCloud()
    framel->raw_disparity_map_.convertTo(framel->raw_disparity_map_, CV_16S, 16);
#else

    // CPU implementation of stereoBM outputs short int, i.e. CV_16S

    cv::Mat left_for_matcher ,right_for_matcher;

   left_for_matcher  = framel->cpu_crop_left.clone();
   right_for_matcher = framer->cpu_crop_right.clone();      
    cv::cvtColor(left_for_matcher,  left_for_matcher,  cv::COLOR_BGR2GRAY);
    cv::cvtColor(right_for_matcher, right_for_matcher, cv::COLOR_BGR2GRAY);

    block_matcher_->compute(left_for_matcher, right_for_matcher, framel->raw_disparity_map_);
    framel->raw_disparity_map_.convertTo(framel->disparity_map_8u_, CV_8UC1, 0.0625);
#endif 

} 


void Disparity_filter::filterDisparityMap(std::shared_ptr<Frame> framel, std::shared_ptr<Frame> framer){

    right_matcher_->compute(framer->cpu_crop_right.clone(),
                                                    framel->cpu_crop_left.clone(),
                                                    raw_right_disparity_map_);

  // Only takes CV_16S type cv::Mat
  wls_filter_->filter(framel->raw_disparity_map_,
                      framel->cpu_crop_left,
                      filtered_disparity_map_,
                      raw_right_disparity_map_);

  filtered_disparity_map_.convertTo(framel->filtered_disparity_map_8u_, CV_8UC1, 0.0625); 

}

код облака точек вычисления


bool PointCloud::initPointCloud(){
    std::string stereo_c2="../calibration/sterolast.xml";  //calib_stereo.xml"; //
  cv::FileStorage ts(stereo_c2,cv::FileStorage::READ);
  if (!ts.isOpened()) {
    std::cerr << "Failed to open calibration parameter file." << std::endl;
    return false;
    }
    cv::Mat P1,P2;
    ts["P1"] >> param_proj_left_;
    ts["P2"] >> param_proj_right_;

  principal_x_ = param_proj_left_.at<double>(0, 2);
  principal_y_ = param_proj_left_.at<double>(1, 2);
  fx_ = param_proj_left_.at<double>(0, 0);
  fy_ = param_proj_left_.at<double>(1, 1);
  baseline_x_fx_ = -param_proj_right_.at<double>(0, 3);
  std::cout<<"** principal_x= " << principal_x_ <<"  ** principal_y= " << principal_y_  <<"  ** fx= " << fx_ <<"  ** fy= " << fy_<<"  ** baseline_x_fx=  " << baseline_x_fx_<<std::endl<< std::flush;
  return true;



    }
void PointCloud::unprojectPtCloud(std::shared_ptr<Frame> framel)
{
  // due to rectification, the image boarder are blank
  // we cut them out
  int border_size = num_disp_;
  const int trunc_img_width_end = HEIGHT - border_size;
  const int trunc_img_height_end = WIDTH - border_size;

   mat_vec3_pt_ = cv::Mat_<cv::Vec3f>(HEIGHT, WIDTH, cv::Vec3f(0, 0, 0));
     cv::Mat color_mat_(HEIGHT, WIDTH, CV_8UC1, &color_buffer_[0])  ;
  for(int v = border_size; v < trunc_img_height_end; ++v)
  {
    for(int u = border_size; u < trunc_img_width_end; ++u)
    {
      cv::Vec3f &point = mat_vec3_pt_.at<cv::Vec3f>(v, u);

#ifdef USE_OPEN_CV_CONTRIB
      float disparity = (float)(framel->raw_disparity_map_.at<short int>(v, u)*0.0625);
#else
      float disparity = (float)(framel->raw_disparity_map_.at<short int>(v, u)*0.0625);
#endif
            //std::cout<<"** disparity " << disparity << std::endl<< std::flush;
      // do not consider pts that are farther than 8.6m, i.e. disparity < 6
      if(disparity >= 60)
      {
        point[2] = baseline_x_fx_/disparity;
        point[0] = (u-principal_x_)*point[2]/fx_;
        point[1] = (v-principal_y_)*point[2]/fy_;
      }
      color_buffer_[v*WIDTH+u] = framel->cpu_crop_left.at<uint8_t>(v, u);
    }
  }

  color_mat_ = cv::Mat(HEIGHT, WIDTH, CV_8UC1, &color_buffer_[0]).clone();
    framel->mat_vec3=mat_vec3_pt_;
    framel->color_m=color_mat_;
    pt_cloud_ = cv::viz::WCloud(mat_vec3_pt_, color_mat_);
}

, когда я вычисляю карту диспаратности и фильтрую ее, я получаю непонятную карту на уровне 100% (мыувидеть области, которые меняют интенсивность света, несмотря на то, что положение камер и препятствия зафиксированы в потоке, не очень ясно, но приемлемо) вы можете увидеть небольшое видео, в котором я протестировал его с файлом калибровки RMS = 0,2.

Тест стереозрения - карта диспаратности

Тест стереозрения - карта диспаратности

облако точек

point cloud result

ВОПРОСЫ

  • - это стереокалибровка, которую я выполнил с ошибкой RMS = 0,20, достаточно для получения четкой карты диспаратностии полная точка облачности поля view из двух камер?

  • Как получить стабильную и чистую карту диспаратности и чистую ГЛУБОКУЮ КАРТУ?

спасибо за любую помощь :)

1 Ответ

0 голосов
/ 13 мая 2019

Как получить стабильную и чистую карту расхождений и чистую ГЛУБОКУЮ КАРТУ?

Чтобы ответить на этот вопрос, я посмотрел видео, которым вы поделились.Отфильтрованная карта диспаратности выглядит хорошо.Фильтр WLS, который вы использовали, дает карту несоответствия точно так же.В этом нет ничего плохого.Но обычно для облаков точек не рекомендуется давать отфильтрованную карту диспаратности в качестве входных данных.Это потому, что фильтр имеет тенденцию заполнять дыры, которые не найдены алгоритмом.Другими словами, это ненадежные данные.Поэтому попробуйте дать нефильтрованную карту диспаратности в качестве входных данных для pointcloud.

Кроме того, средство просмотра, которое вы используете для просмотра облака точек, т. Е. Meshlab часто имеет тенденцию поглощать некоторые точки.Таким образом, вы можете использовать другие средства просмотра, такие как CloudCompare.

- это стереокалибровка, которую я выполнил с ошибкой RMS = 0,20, достаточно для получения четкой карты диспаратности и полной точки облачности поля зрения.из двух камер?

Да, для большинства случаев достаточно ошибки 0,20 RMS.Но опять же, чем меньше, тем лучше.

...