Настройка оптимального выравнивания шаблона PCL

У меня есть 2 облака точек (в миллиметрах), одно представляет собой «сетку», взятую из объекта stl (99999 точек), а второе — облако точек этого объекта, снятое 3D-камерой (около 30841 точек). Я использую код этого руководства PCL для сопоставления шаблонов: http://pointclouds.org/documentation/tutorials/template_alignment.php. После этого я использую код PCL ICP для окончательного выравнивания. Но я все еще получаю довольно плохое начальное предположение от выравнивания шаблона. (например, без вращения, полуматч,...)

Я попытался изменить настройки с:

normal_radius_(0.02f)
feature_radius_(0.02f)
min_sample_distance_(0.05f)
max_correspondence_distance_(0.01f * 0.01f)
nr_iterations_(50)

к этому:

normal_radius_(2.0f)
feature_radius_(2.0f)
min_sample_distance_(0.5f)
max_correspondence_distance_(1.0f * 1.0f)
nr_iterations_(1000)

Может кто-нибудь, пожалуйста, дайте мне несколько советов, как улучшить этот код? Спасибо!


person John117    schedule 25.04.2019    source источник


Ответы (2)


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

Некоторые примеры:

  • normal_radius: 4-8 * <resolution>
    Чтобы вычислить хорошие нормали, на подстилающей поверхности должно быть достаточно точек, чтобы представить стабильную поверхность. Если ваши юниты находятся в mm, то вы выбрали радиус 2mm, что слишком мало.
  • feature_radius: 1-2 * <normal_radius>
    То же самое относится к вычислению функций, что и к нормалям.
  • max_correspondence_distance: Вы устанавливаете это значение равным 1mm*1mm, что означает, что корреспонденция может быть разделена только на 1mm, чтобы быть классифицированной как корреспонденция. Здесь важно использовать значение, соответствующее размеру вашего объекта. Вы должны спросить себя: "Каково максимально допустимое расстояние между моим объектом и эталоном, чтобы мой объект все еще совпадал?" Если вы сравниваете лица, вы должны использовать некоторые centimeter, например. 1cm-5cm, так как лицо довольно маленькое. Но допустим, вы хотите сравнить большие объекты, такие как здания. Там вы можете использовать значения до 1m.
  • min_sample_distance: Здесь почти то же самое, что и для max_correspondence_distance. Вы должны спросить себя: "Насколько образец должен быть удален от другого образца?". Чем меньше значение, тем больше образцов вы получите. Опять же, выберите значение, которое составляет часть размера вашего объекта, но также учтите, что оно не должно быть меньше, чем разрешение вашего облака. Вы установили его на 0.5mm, что слишком мало.
  • nr_iterations: Обычно это не так важно, но допустимы значения между 100-500.
person kanstar    schedule 02.05.2019

normal_radius_:

  • Выберите в соответствии с плотностью вашего облака (вы хотите, чтобы оно было достаточно большим, чтобы захватить достаточное количество точек в окружающей среде — если оно слишком маленькое, нормаль будет шумной, вплоть до полного мусора или не сможет вычислить)
  • Примите во внимание гладкость вашего облака (вы хотите, чтобы оно было достаточно маленьким, чтобы было правильно приблизить локальную среду к плоскости — если оно слишком велико, нормаль будет слишком гладкой и игнорирует мелкие детали)

min_sample_distance_:

  • В основном вычислительный аспект. Чем больше расстояние выборки, тем быстрее он будет работать.
  • Если он слишком большой, вы теряете точность выравнивания.

feature_radius_:

  • Вам нужно учитывать, в каком масштабе у вас есть дискриминационные структуры/формы.
  • Например, с лицами у меня был успех с радиусом элемента около 1/10 размера модели.

max_correspondence_distance_:

  • Зависит от ваших начальных условий - как далеко могут быть 2 соответствующие точки. Предоставление начального предположения с использованием некоторой эвристики может помочь вам уменьшить этот параметр и улучшить как производительность, так и результаты.
  • Обратите внимание, что это квадрат расстояния

В вашем случае (два облака одного и того же объекта), если ваше облако имеет нормали, хорошее начальное предположение может быть достигнуто без использования SampleConsensusInitialAlignment вообще. Просто выровняйте среднюю нормаль обоих облаков. Вы можете применить следующий метод к обоим вашим облакам, чтобы поместить их в «нормализованное» положение и ориентацию:

void ToOrigin(pcl::PointCloud<pcl::PointXYZINormal>::Ptr cloud, Eigen::Affine3f & transformation, Eigen::Vector3f up, float resolution)
{
    // Calc Origin

    pcl::PointXYZINormal origin;
    auto size = cloud->points.size();
    for (auto pointItr = cloud->begin(); pointItr != cloud->end(); pointItr++)
    {
        origin.getArray3fMap() += pointItr->getArray3fMap() / size;
        origin.getNormalVector3fMap() += pointItr->getNormalVector3fMap();
    }
    origin.getNormalVector3fMap().normalize();

    // Calc Transformation  

    auto proj = origin.getNormalVector3fMap().dot(up) * origin.getNormalVector3fMap();

    // the direction that will be rotated to y_axis
    // (the part of "up" that is perpendicular to the cloud normal)
    auto y_direction = (up - proj).normalized();

    // the direction that will be rotated to z_axis
    auto z_direction = origin.getNormalVector3fMap();   

    // the point that will be shifted to origin (0,0,0)
    auto center = origin.getArray3fMap();               

    pcl::getTransformationFromTwoUnitVectorsAndOrigin(y_direction, z_direction, center, transformation);

    // Transform

    pcl::PointCloud<pcl::PointXYZINormal> cloud_tmp;
    pcl::transformPointCloudWithNormals(*cloud, cloud_tmp, transformation);
    pcl::copyPointCloud(cloud_tmp, *cloud);
}
person Mark Loyman    schedule 02.05.2019