как получить чистую карту несоответствия и чистую КАРТУ ГЛУБИНЫ

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

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

неректифицированные изображения

неректифицированные изображения

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

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

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

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

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

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

  1. Я взял на себя функции 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.

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

тест стереозрения - карта несоответствия

облако точек

результат облака точек

ВОПРОСЫ

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

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

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


person Mohand    schedule 09.05.2019    source источник


Ответы (1)


Как получить стабильную и чистую карту диспаратности и чистую карту глубины?

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

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

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

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

person Madhu Soodhan    schedule 13.05.2019