如何抑制来自 pointcloudlibrary `SampleConsensusModelPlane::optimizeModelCoefficients` 的恼人警告流

How to suppress annoying stream of warnings from pointcloudlibrary `SampleConsensusModelPlane::optimizeModelCoefficients`

我有使用 PCL 的 sac 模型拟合将平面拟合到点云的功能。我想要我能得到的最好结果,所以我想 运行 和 seg.setOptimizeCoefficients(true)

问题是很多时候传入的点云没有足够的点来优化系数,所以我得到了一个连续的流:

[pcl::SampleConsensusModelPlane::optimizeModelCoefficients] Not enough inliers found to optimize model coefficients (0)! Returning the same coefficients.

我希望在可以的情况下将系数优化到 运行,而在不可以的情况下继续进行而不用许多红色警告消息污染 CLI 输出。

根据this issue,此消息仅表示 SAC 模型拟合的内点少于 3 个。我确实提取了内点,所以我可以手动检查是否有 3 个或更多。但我看不出如何先做到这一点,然后再找到优化的模型系数。有办法吗?

inline void fit_plane_to_points(                                               
    const pcl::PointCloud<pcl::PointXYZI>::ConstPtr& det_points,               
    const pcl::ModelCoefficients::Ptr& coefficients,                           
    const Eigen::Vector3f& vec,                                                
    const pcl::PointCloud<pcl::PointXYZI>::Ptr& inlier_pts) {                  
                                                                               
  // if no det points to work with, don't try and segment                      
  if (det_points->size() < 3) {                                                
    return;                                                                    
  }                                                                            
                                                                               
  // fit surface point samples to a plane                                      
  pcl::PointIndices::Ptr inlier_indices(new pcl::PointIndices);                
  pcl::SACSegmentation<pcl::PointXYZI> seg;                                    
  seg.setModelType(pcl::SACMODEL_PERPENDICULAR_PLANE);                         
  // max allowed difference between the plane normal and the given axis        
  seg.setEpsAngle(sac_angle_threshold_);                                       
  seg.setAxis(vec);                                                            
  seg.setMethodType(pcl::SAC_RANSAC);                                          
  seg.setDistanceThreshold(sac_distance_threshold_);                           
  seg.setMaxIterations(1000);                                                  
  seg.setInputCloud(det_points);                                               
  seg.setOptimizeCoefficients(sac_optimise_coefficients_);                     
  seg.segment(*inlier_indices, *coefficients);                                 
                                                                               
  if (inlier_indices->indices.empty()) {                                       
    // if no inlier points don't try and extract                               
    return;                                                                    
  }                                                                            
  // extract the planar points                                                 
  pcl::ExtractIndices<pcl::PointXYZI> extract;                                 
  extract.setInputCloud(det_points);                                           
  extract.setIndices(inlier_indices);                                          
  extract.setNegative(false);                                                  
  extract.filter(*inlier_pts);                                                 
  return;                                                                      
}  

我认为最好的方法是禁用 setOptimizeCoefficients,然后在 seg.segment 之后手动执行此操作。您基本上必须重新创建这些行: https://github.com/PointCloudLibrary/pcl/blob/10235c9c1ad47989bdcfebe47f4a369871357e2a/segmentation/include/pcl/segmentation/impl/sac_segmentation.hpp#L115-L123 。 您可以通过 getModel() (https://pointclouds.org/documentation/classpcl_1_1_s_a_c_segmentation.html#ac7b9564ceba35754837b4848cf448d78).

访问模型

根据 IBitMyBytes 的建议,通过设置 seg.setOptimizeCoefficients(false);,然后在我自己检查后手动优化,最终使它工作:

  // if we can, optimise model coefficients                                    
  if (sac_optimise_coefficients_ && inlier_indices->indices.size() > 4) {      
    pcl::SampleConsensusModel<pcl::PointXYZI>::Ptr model = seg.getModel();     
    Eigen::VectorXf coeff_refined;                                             
    Eigen::Vector4f coeff_raw(coefficients->values.data());                    
    model->optimizeModelCoefficients(inlier_indices->indices,                  
                                     coeff_raw, coeff_refined);                
    coefficients->values.resize(coeff_refined.size());                         
    memcpy(&coefficients->values[0], &coeff_refined[0],                        
           coeff_refined.size() * sizeof (float));                             
    // Refine inliers                                                          
    model->selectWithinDistance(coeff_refined, sac_distance_threshold_,        
                                inlier_indices->indices);                      
  }