• pcl--第十一节 点云外接立方体和点云模板匹配


    点云外接立方体(3D物体包容盒)

    使用pcl::MomentOfInertiaEstimation类来获取基于偏心率和惯性矩的描述符。该类还允许提取云的轴对齐和定向的边界框。但是提取的OBB并非最小可能的边界框。

    原理简述

    包围体(包容盒)是一个简单的几何空间,里面包含着复杂形状的物体。为物体添加包围体的目的是快速的进行碰撞检测或者进行精确的碰撞检测之前进行过滤(即当包围体碰撞,才进行精确碰撞检测和处理)。包围体类型包括球体、轴对齐包围盒(AABB)、有向包围盒(OBB)、8-DOP以及凸壳(CONVEX HULL)。

    常见包容盒( Bounding Volumes)分类:

    • 包容球:SPHERE 用球体包围整个几何体,用于相交测试很方便,但是其紧密型差,周围空隙较大,当物体变形后,包围球需要重新计算。当对象进行旋转运动时,包围球不需要做任何更新,这是包围球的优势,即当几何对象频繁进行旋转运动时,使用包围球效率较高。
    • AABB包容盒:Axially Aligned Bounding Box,3D环境下的AABB盒即一个六面体,每个边都平行于一个坐标平面,较简单,但紧密性较差,当物体旋转、形变之后需要对AABB进行更新。本身的长宽高根据物体大小而定。
    • OBB包容盒:Oriented Bounding Box,此方法紧密型较好,可以降低参与相交测试的包容盒数目,因此性能要优于AABB和包容球。当物体发生旋转,仅需对OBB进行相同的旋转即可,但是当物体形变后,更新OBB的代价较大,故不适用那些软体的对象。

    如上图所示,还有K-DOP,CONVEX HULL等包容盒,越靠右,包容效果好、越紧密。但是检测速度更慢,也更消耗内存资源。

    1. #include
    2. #include
    3. #include
    4. #include
    5. #include
    6. #include
    7. using namespace std::chrono_literals;
    8. int main (int argc, char** argv)
    9. {
    10. //if (argc != 2)
    11. // return (0);
    12. pcl::PointCloud::Ptr cloud (new pcl::PointCloud ());
    13. if (pcl::io::loadPCDFile ("table_scene_lms400_downsampled.pcd", *cloud) == -1)
    14. return (-1);
    15. pcl::MomentOfInertiaEstimation feature_extractor;
    16. feature_extractor.setInputCloud (cloud);
    17. feature_extractor.compute ();
    18. std::vector <float> moment_of_inertia;
    19. std::vector <float> eccentricity;
    20. pcl::PointXYZ min_point_AABB;
    21. pcl::PointXYZ max_point_AABB;
    22. pcl::PointXYZ min_point_OBB;
    23. pcl::PointXYZ max_point_OBB;
    24. pcl::PointXYZ position_OBB;
    25. Eigen::Matrix3f rotational_matrix_OBB;
    26. float major_value, middle_value, minor_value;
    27. Eigen::Vector3f major_vector, middle_vector, minor_vector;
    28. Eigen::Vector3f mass_center;
    29. feature_extractor.getMomentOfInertia (moment_of_inertia);
    30. feature_extractor.getEccentricity (eccentricity);
    31. feature_extractor.getAABB (min_point_AABB, max_point_AABB);
    32. feature_extractor.getOBB (min_point_OBB, max_point_OBB, position_OBB, rotational_matrix_OBB);
    33. feature_extractor.getEigenValues (major_value, middle_value, minor_value);
    34. feature_extractor.getEigenVectors (major_vector, middle_vector, minor_vector);
    35. feature_extractor.getMassCenter (mass_center);
    36. pcl::visualization::PCLVisualizer::Ptr viewer (new pcl::visualization::PCLVisualizer ("3D Viewer"));
    37. viewer->setBackgroundColor (0, 0, 0);
    38. viewer->addCoordinateSystem (1);
    39. viewer->initCameraParameters ();
    40. viewer->addPointCloud (cloud, "sample cloud");
    41. viewer->addCube (min_point_AABB.x, max_point_AABB.x, min_point_AABB.y, max_point_AABB.y, min_point_AABB.z, max_point_AABB.z, 1.0, 1.0, 0.0, "AABB");
    42. viewer->setShapeRenderingProperties(pcl::visualization::PCL_VISUALIZER_REPRESENTATION, pcl::visualization::PCL_VISUALIZER_REPRESENTATION_WIREFRAME, "AABB");
    43. Eigen::Vector3f position (position_OBB.x, position_OBB.y, position_OBB.z);
    44. Eigen::Quaternionf quat (rotational_matrix_OBB);
    45. viewer->addCube (position, quat, max_point_OBB.x - min_point_OBB.x, max_point_OBB.y - min_point_OBB.y, max_point_OBB.z - min_point_OBB.z, "OBB");
    46. viewer->setShapeRenderingProperties(pcl::visualization::PCL_VISUALIZER_REPRESENTATION, pcl::visualization::PCL_VISUALIZER_REPRESENTATION_WIREFRAME, "OBB");
    47. pcl::PointXYZ center (mass_center (0), mass_center (1), mass_center (2));
    48. pcl::PointXYZ x_axis (major_vector (0) + mass_center (0), major_vector (1) + mass_center (1), major_vector (2) + mass_center (2));
    49. pcl::PointXYZ y_axis (middle_vector (0) + mass_center (0), middle_vector (1) + mass_center (1), middle_vector (2) + mass_center (2));
    50. pcl::PointXYZ z_axis (minor_vector (0) + mass_center (0), minor_vector (1) + mass_center (1), minor_vector (2) + mass_center (2));
    51. viewer->addLine (center, x_axis, 1.0f, 0.0f, 0.0f, "major eigen vector");
    52. viewer->addLine (center, y_axis, 0.0f, 1.0f, 0.0f, "middle eigen vector");
    53. viewer->addLine (center, z_axis, 0.0f, 0.0f, 1.0f, "minor eigen vector");
    54. while(!viewer->wasStopped())
    55. {
    56. viewer->spinOnce (100);
    57. std::this_thread::sleep_for(100ms);
    58. }
    59. return (0);
    60. }

    黄色立方体为AABB包容盒,白色立方体为OBB包容盒 

     点云模板匹配

    1. #include
    2. #include
    3. #include
    4. #include
    5. #include
    6. #include
    7. #include
    8. #include
    9. #include
    10. #include
    11. #include
    12. #include
    13. #include
    14. #include
    15. #include
    16. class FeatureCloud
    17. {
    18. public:
    19. // A bit of shorthand
    20. typedef pcl::PointCloud PointCloud;
    21. typedef pcl::PointCloud SurfaceNormals;
    22. typedef pcl::PointCloud LocalFeatures;
    23. typedef pcl::search::KdTree SearchMethod;
    24. FeatureCloud () :
    25. search_method_xyz_ (new SearchMethod),
    26. normal_radius_ (0.02f),
    27. feature_radius_ (0.02f)
    28. {}
    29. ~FeatureCloud () {}
    30. // Process the given cloud
    31. void
    32. setInputCloud (PointCloud::Ptr xyz)
    33. {
    34. xyz_ = xyz;
    35. processInput ();
    36. }
    37. // Load and process the cloud in the given PCD file
    38. void
    39. loadInputCloud (const std::string &pcd_file)
    40. {
    41. xyz_ = PointCloud::Ptr (new PointCloud);
    42. pcl::io::loadPCDFile (pcd_file, *xyz_);
    43. processInput ();
    44. }
    45. // Get a pointer to the cloud 3D points
    46. PointCloud::Ptr
    47. getPointCloud () const
    48. {
    49. return (xyz_);
    50. }
    51. // Get a pointer to the cloud of 3D surface normals
    52. SurfaceNormals::Ptr
    53. getSurfaceNormals () const
    54. {
    55. return (normals_);
    56. }
    57. // Get a pointer to the cloud of feature descriptors
    58. LocalFeatures::Ptr
    59. getLocalFeatures () const
    60. {
    61. return (features_);
    62. }
    63. protected:
    64. // Compute the surface normals and local features
    65. void
    66. processInput ()
    67. {
    68. computeSurfaceNormals ();
    69. computeLocalFeatures ();
    70. }
    71. // Compute the surface normals
    72. void
    73. computeSurfaceNormals ()
    74. {
    75. normals_ = SurfaceNormals::Ptr (new SurfaceNormals);
    76. pcl::NormalEstimation norm_est;
    77. norm_est.setInputCloud (xyz_);
    78. norm_est.setSearchMethod (search_method_xyz_);
    79. norm_est.setRadiusSearch (normal_radius_);
    80. norm_est.compute (*normals_);
    81. }
    82. // Compute the local feature descriptors
    83. void
    84. computeLocalFeatures ()
    85. {
    86. features_ = LocalFeatures::Ptr (new LocalFeatures);
    87. pcl::FPFHEstimation fpfh_est;
    88. fpfh_est.setInputCloud (xyz_);
    89. fpfh_est.setInputNormals (normals_);
    90. fpfh_est.setSearchMethod (search_method_xyz_);
    91. fpfh_est.setRadiusSearch (feature_radius_);
    92. fpfh_est.compute (*features_);
    93. }
    94. private:
    95. // Point cloud data
    96. PointCloud::Ptr xyz_;
    97. SurfaceNormals::Ptr normals_;
    98. LocalFeatures::Ptr features_;
    99. SearchMethod::Ptr search_method_xyz_;
    100. // Parameters
    101. float normal_radius_;
    102. float feature_radius_;
    103. };
    104. class TemplateAlignment
    105. {
    106. public:
    107. // A struct for storing alignment results
    108. struct Result
    109. {
    110. float fitness_score;
    111. Eigen::Matrix4f final_transformation;
    112. PCL_MAKE_ALIGNED_OPERATOR_NEW
    113. };
    114. TemplateAlignment () :
    115. min_sample_distance_ (0.05f),
    116. max_correspondence_distance_ (0.01f*0.01f),
    117. nr_iterations_ (500)
    118. {
    119. // Initialize the parameters in the Sample Consensus Initial Alignment (SAC-IA) algorithm
    120. sac_ia_.setMinSampleDistance (min_sample_distance_);
    121. sac_ia_.setMaxCorrespondenceDistance (max_correspondence_distance_);
    122. sac_ia_.setMaximumIterations (nr_iterations_);
    123. }
    124. ~TemplateAlignment () {}
    125. // Set the given cloud as the target to which the templates will be aligned
    126. void
    127. setTargetCloud (FeatureCloud &target_cloud)
    128. {
    129. target_ = target_cloud;
    130. sac_ia_.setInputTarget (target_cloud.getPointCloud ());
    131. sac_ia_.setTargetFeatures (target_cloud.getLocalFeatures ());
    132. }
    133. // Add the given cloud to the list of template clouds
    134. void
    135. addTemplateCloud (FeatureCloud &template_cloud)
    136. {
    137. templates_.push_back (template_cloud);
    138. }
    139. // Align the given template cloud to the target specified by setTargetCloud ()
    140. void
    141. align (FeatureCloud &template_cloud, TemplateAlignment::Result &result)
    142. {
    143. sac_ia_.setInputSource (template_cloud.getPointCloud ());
    144. sac_ia_.setSourceFeatures (template_cloud.getLocalFeatures ());
    145. pcl::PointCloud registration_output;
    146. sac_ia_.align (registration_output);
    147. result.fitness_score = (float) sac_ia_.getFitnessScore (max_correspondence_distance_);
    148. result.final_transformation = sac_ia_.getFinalTransformation ();
    149. }
    150. // Align all of template clouds set by addTemplateCloud to the target specified by setTargetCloud ()
    151. void
    152. alignAll (std::vector > &results)
    153. {
    154. results.resize (templates_.size ());
    155. for (std::size_t i = 0; i < templates_.size (); ++i)
    156. {
    157. align (templates_[i], results[i]);
    158. }
    159. }
    160. // Align all of template clouds to the target cloud to find the one with best alignment score
    161. int
    162. findBestAlignment (TemplateAlignment::Result &result)
    163. {
    164. // Align all of the templates to the target cloud
    165. std::vector > results;
    166. alignAll (results);
    167. // Find the template with the best (lowest) fitness score
    168. float lowest_score = std::numeric_limits<float>::infinity ();
    169. int best_template = 0;
    170. for (std::size_t i = 0; i < results.size (); ++i)
    171. {
    172. const Result &r = results[i];
    173. if (r.fitness_score < lowest_score)
    174. {
    175. lowest_score = r.fitness_score;
    176. best_template = (int) i;
    177. }
    178. }
    179. // Output the best alignment
    180. result = results[best_template];
    181. return (best_template);
    182. }
    183. private:
    184. // A list of template clouds and the target to which they will be aligned
    185. std::vector templates_;
    186. FeatureCloud target_;
    187. // The Sample Consensus Initial Alignment (SAC-IA) registration routine and its parameters
    188. pcl::SampleConsensusInitialAlignment sac_ia_;
    189. float min_sample_distance_;
    190. float max_correspondence_distance_;
    191. int nr_iterations_;
    192. };
    193. // Align a collection of object templates to a sample point cloud
    194. int
    195. main (int argc, char **argv)
    196. {
    197. if (argc < 3)
    198. {
    199. printf ("No target PCD file given!\n");
    200. return (-1);
    201. }
    202. // Load the object templates specified in the object_templates.txt file
    203. std::vector object_templates;
    204. std::ifstream input_stream (argv[1]);
    205. object_templates.resize (0);
    206. std::string pcd_filename;
    207. while (input_stream.good ())
    208. {
    209. std::getline (input_stream, pcd_filename);
    210. if (pcd_filename.empty () || pcd_filename.at (0) == '#') // Skip blank lines or comments
    211. continue;
    212. FeatureCloud template_cloud;
    213. template_cloud.loadInputCloud (pcd_filename);
    214. object_templates.push_back (template_cloud);
    215. }
    216. input_stream.close ();
    217. // Load the target cloud PCD file
    218. pcl::PointCloud::Ptr cloud (new pcl::PointCloud);
    219. pcl::io::loadPCDFile (argv[2], *cloud);
    220. // Preprocess the cloud by...
    221. // ...removing distant points
    222. const float depth_limit = 1.0;
    223. pcl::PassThrough pass;
    224. pass.setInputCloud (cloud);
    225. pass.setFilterFieldName ("z");
    226. pass.setFilterLimits (0, depth_limit);
    227. pass.filter (*cloud);
    228. // ... and downsampling the point cloud
    229. const float voxel_grid_size = 0.005f;
    230. pcl::VoxelGrid vox_grid;
    231. vox_grid.setInputCloud (cloud);
    232. vox_grid.setLeafSize (voxel_grid_size, voxel_grid_size, voxel_grid_size);
    233. //vox_grid.filter (*cloud); // Please see this http://www.pcl-developers.org/Possible-problem-in-new-VoxelGrid-implementation-from-PCL-1-5-0-td5490361.html
    234. pcl::PointCloud::Ptr tempCloud (new pcl::PointCloud);
    235. vox_grid.filter (*tempCloud);
    236. cloud = tempCloud;
    237. // Assign to the target FeatureCloud
    238. FeatureCloud target_cloud;
    239. target_cloud.setInputCloud (cloud);
    240. // Set the TemplateAlignment inputs
    241. TemplateAlignment template_align;
    242. for (std::size_t i = 0; i < object_templates.size (); ++i)
    243. {
    244. template_align.addTemplateCloud (object_templates[i]);
    245. }
    246. template_align.setTargetCloud (target_cloud);
    247. // Find the best template alignment
    248. TemplateAlignment::Result best_alignment;
    249. int best_index = template_align.findBestAlignment (best_alignment);
    250. const FeatureCloud &best_template = object_templates[best_index];
    251. // Print the alignment fitness score (values less than 0.00002 are good)
    252. printf ("Best fitness score: %f\n", best_alignment.fitness_score);
    253. // Print the rotation matrix and translation vector
    254. Eigen::Matrix3f rotation = best_alignment.final_transformation.block<3,3>(0, 0);
    255. Eigen::Vector3f translation = best_alignment.final_transformation.block<3,1>(0, 3);
    256. printf ("\n");
    257. printf (" | %6.3f %6.3f %6.3f | \n", rotation (0,0), rotation (0,1), rotation (0,2));
    258. printf ("R = | %6.3f %6.3f %6.3f | \n", rotation (1,0), rotation (1,1), rotation (1,2));
    259. printf (" | %6.3f %6.3f %6.3f | \n", rotation (2,0), rotation (2,1), rotation (2,2));
    260. printf ("\n");
    261. printf ("t = < %0.3f, %0.3f, %0.3f >\n", translation (0), translation (1), translation (2));
    262. // Save the aligned template for visualization
    263. pcl::PointCloud transformed_cloud;
    264. pcl::transformPointCloud (*best_template.getPointCloud (), transformed_cloud, best_alignment.final_transformation);
    265. pcl::io::savePCDFileBinary ("output.pcd", transformed_cloud);
    266. return (0);
    267. }

  • 相关阅读:
    【微信小程序】前端+后端 :第一篇(基于javaweb 案例)
    《ToDesk云电脑vs青椒云性能测试,谁更能实现游戏自由?》
    【node进阶】深入浅出前后端身份验证(下)---JWT
    全球第4大操作系统(鸿蒙)的软件后缀.hap
    VB 语言介绍以及VBA、宏(Macro)的关系
    YOLO目标检测——卫星遥感多类别检测数据集下载分享【含对应voc、coco和yolo三种格式标签】
    【Azure 应用服务】Azure Function 启用 Managed Identity后, Powershell Funciton出现 ERROR: ManagedIdentityCredential authentication failed
    雷达编程实战之功耗优化技术(低功耗)
    企业管理软件使用与择选时要注意五点
    深入解析Java HashMap的Resize源码
  • 原文地址:https://blog.csdn.net/weixin_42398658/article/details/133167211