• PCL交互选择ROI区域


    PCL的配置和如何配准点云可见博主之前的博客

    win10环境下PCL安装和配置回顾(一)_竹叶青lvye的博客-CSDN博客_pcl win10

    win10环境下PCL安装和配置回顾(二)_竹叶青lvye的博客-CSDN博客_win10 安装pcl

    PCL - 3D点云配准(registration)介绍_竹叶青lvye的博客-CSDN博客

    其它的PCL方面常用的一些点云算法,可自己花时间去研读,这边想去简单实现下ROI区域交互式的选择,接下还是延续前面几篇博客所用的PCL的配置。

    一. 生成测试点云

    这边点云选择

    mirrors / pointcloudlibrary / data · GitCode

    里面的learn5.pcd点云

     这里自定义了一个旋转平移矩阵(将点云通过这个变换为另外一个点云),详细见如下代码:

    1. #include // for pcl::make_shared
    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. using pcl::visualization::PointCloudColorHandlerGenericField;
    15. using pcl::visualization::PointCloudColorHandlerCustom;
    16. //convenient typedefs
    17. typedef pcl::PointXYZ PointT;
    18. typedef pcl::PointCloud PointCloud;
    19. typedef pcl::PointNormal PointNormalT;
    20. typedef pcl::PointCloud PointCloudWithNormals;
    21. int main()
    22. {
    23. PointCloud::Ptr cloud_src(new PointCloud);
    24. PointCloud::Ptr cloud_tgt(new PointCloud);
    25. pcl::io::loadPCDFile("D:\\PCL\\data-master\\segmentation\\mOSD\\learn\\learn5.pcd", *cloud_src);
    26. Eigen::Matrix4f transform_1 = Eigen::Matrix4f::Identity();//定义绕X轴的旋转矩阵,并初始化为单位阵
    27. float theta = M_PI / 4; // The angle of rotation in radians
    28. transform_1(0, 0) = std::cos(theta);
    29. transform_1(0, 1) = -sin(theta);
    30. transform_1(1, 0) = sin(theta);
    31. transform_1(1, 1) = std::cos(theta);
    32. transform_1(0, 3) = 0.7f;
    33. transform_1(1, 3) = 0.6f;
    34. transform_1(2, 3) = 1.2f;
    35. pcl::transformPointCloud(*cloud_src, *cloud_tgt, transform_1);
    36. std::cout << "cloud_src size: " << cloud_src->size() << std::endl;
    37. std::cout << "cloud_target size: " << cloud_tgt->size() << std::endl;
    38. pcl::visualization::PCLVisualizer* p;
    39. int vp_1, vp_2;
    40. p = new pcl::visualization::PCLVisualizer("view");
    41. PointCloudColorHandlerCustom src_h(cloud_src, 255, 0, 0);
    42. PointCloudColorHandlerCustom tgt_h(cloud_tgt, 0, 255, 0);
    43. p->addPointCloud(cloud_src, src_h, "vp1_src");
    44. p->addPointCloud(cloud_tgt, tgt_h, "vp1_target");
    45. p->spin();
    46. return (0);
    47. }

     运行结果如下:

    二. 交互点选

    接下来在变换前的点云数据上点选一个ROI区域,代码如下:

    1. #include // for pcl::make_shared
    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. #include
    17. #include
    18. using pcl::visualization::PointCloudColorHandlerGenericField;
    19. using pcl::visualization::PointCloudColorHandlerCustom;
    20. //convenient typedefs
    21. typedef pcl::PointXYZ PointT;
    22. typedef pcl::PointCloud PointCloud;
    23. typedef pcl::PointNormal PointNormalT;
    24. typedef pcl::PointCloud PointCloudWithNormals;
    25. //Mutex
    26. boost::mutex cloud_mutex;
    27. struct callback_args
    28. {
    29. PointCloud::Ptr clicked_points_3d;
    30. pcl::visualization::PCLVisualizer::Ptr viewerPtr;
    31. };
    32. //点选函数
    33. void pointPick_callback(const pcl::visualization::PointPickingEvent& event, void* args)
    34. {
    35. struct callback_args* data = (struct callback_args*)args;
    36. if (event.getPointIndex() == -1)
    37. {
    38. return;
    39. }
    40. //提取当前点
    41. PointT current_point;
    42. event.getPoint(current_point.x, current_point.y, current_point.z);
    43. data->clicked_points_3d->points.push_back(current_point);
    44. //显示当前点
    45. pcl::visualization::PointCloudColorHandlerCustom red(data->clicked_points_3d, 255, 0, 0);
    46. data->viewerPtr->removePointCloud("clicked_points");
    47. data->viewerPtr->addPointCloud(data->clicked_points_3d, red, "clicked_points");
    48. data->viewerPtr->setPointCloudRenderingProperties(pcl::visualization::PCL_VISUALIZER_POINT_SIZE, 10, "clicked_points");
    49. cout << current_point << endl;
    50. }
    51. int main()
    52. {
    53. PointCloud::Ptr cloud_src(new PointCloud);
    54. PointCloud::Ptr cloud_tgt(new PointCloud);
    55. pcl::io::loadPCDFile("D:\\PCL\\data-master\\segmentation\\mOSD\\learn\\learn5.pcd", *cloud_src);
    56. Eigen::Matrix4f transform_1 = Eigen::Matrix4f::Identity();//定义绕X轴的旋转矩阵,并初始化为单位阵
    57. float theta = M_PI / 4; // The angle of rotation in radians
    58. transform_1(0, 0) = std::cos(theta);
    59. transform_1(0, 1) = -sin(theta);
    60. transform_1(1, 0) = sin(theta);
    61. transform_1(1, 1) = std::cos(theta);
    62. transform_1(0, 3) = 0.7f;
    63. transform_1(1, 3) = 0.6f;
    64. transform_1(2, 3) = 1.2f;
    65. pcl::transformPointCloud(*cloud_src, *cloud_tgt, transform_1);
    66. std::cout << "cloud_src size: " << cloud_src->size() << std::endl;
    67. std::cout << "cloud_target size: " << cloud_tgt->size() << std::endl;
    68. pcl::visualization::PCLVisualizer* p;
    69. p = new pcl::visualization::PCLVisualizer("view");
    70. cloud_mutex.lock(); // for not overwriting the point cloud
    71. PointCloudColorHandlerCustom src_h(cloud_src, 0, 0, 255);
    72. PointCloudColorHandlerCustom tgt_h(cloud_tgt, 0, 255, 0);
    73. p->setBackgroundColor(0.5, 0.5, 0.1, 0); // 设置背景为深灰
    74. p->addPointCloud(cloud_src, src_h, "vp1_src");
    75. p->addPointCloud(cloud_tgt, tgt_h, "vp1_target");
    76. struct callback_args cb_args;
    77. PointCloud::Ptr clicked_points_3d(new PointCloud);
    78. cb_args.clicked_points_3d = clicked_points_3d;
    79. cb_args.viewerPtr = pcl::visualization::PCLVisualizer::Ptr(p);
    80. p->registerPointPickingCallback(pointPick_callback, (void*)&cb_args);
    81. cout << "->Shift + 鼠标左键选点,按 ‘Q’结束选点" << endl;
    82. p->spin();
    83. cout << "->选点结束" << endl;
    84. Eigen::Affine3f affine(transform_1);
    85. PointT conver_point = pcl::transformPoint(cb_args.clicked_points_3d->points[0], affine);
    86. std::cout << "use the affine to covert the point: " << std::endl;
    87. std::cout << conver_point << std::endl;
    88. cloud_mutex.unlock();
    89. while (!p->wasStopped())
    90. {
    91. p->spinOnce(100);
    92. boost::this_thread::sleep(boost::posix_time::microseconds(100000));
    93. }
    94. return (0);
    95. }

    运行程序,可看到如下先点选了蓝色点云上的一个角点,又鼠标点选了绿色点云上对应位置处的一角点。这个两个点云的点同时也在点云上show出来了。

     按了Q退出点选模式后,程序会将点云的绿色处的点去由变换矩阵变化下,算出来的值,可看到和上面鼠标点选的绿色点云的角点坐标是近似的。

     

    三. 将点云上的ROI区域跟随目标的变换而变化,并在其变换后的点云数据上画出立体框

    代码如下,在第一个点云上可以通过鼠标点选ROI区域,完毕后会在第二个点云上会产生一个ROI区域,可看到是跟随目标变化的。

    1. #include // for pcl::make_shared
    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. #include
    17. #include
    18. #include
    19. using pcl::visualization::PointCloudColorHandlerGenericField;
    20. using pcl::visualization::PointCloudColorHandlerCustom;
    21. //convenient typedefs
    22. typedef pcl::PointXYZ PointT;
    23. typedef pcl::PointCloud PointCloud;
    24. typedef pcl::PointNormal PointNormalT;
    25. typedef pcl::PointCloud PointCloudWithNormals;
    26. pcl::PointCloud::Ptr points;
    27. //Mutex
    28. boost::mutex cloud_mutex;
    29. int count = 0;
    30. struct callback_args
    31. {
    32. PointCloud::Ptr clicked_points_3d;
    33. PointCloud::Ptr clicked_points_3d_convert;
    34. pcl::visualization::PCLVisualizer::Ptr viewerPtr;
    35. Eigen::Affine3f affine;
    36. };
    37. //点选函数
    38. void pointPick_callback(const pcl::visualization::PointPickingEvent& event, void* args)
    39. {
    40. count++;
    41. struct callback_args* data = (struct callback_args*)args;
    42. if (event.getPointIndex() == -1)
    43. {
    44. return;
    45. }
    46. //提取当前点
    47. PointT current_point;
    48. event.getPoint(current_point.x, current_point.y, current_point.z);
    49. data->clicked_points_3d->points.push_back(current_point);
    50. //显示当前点
    51. pcl::visualization::PointCloudColorHandlerCustom red(data->clicked_points_3d, 255, 0, 0);
    52. data->viewerPtr->removePointCloud("clicked_points");
    53. data->viewerPtr->addPointCloud(data->clicked_points_3d, red, "clicked_points");
    54. data->viewerPtr->setPointCloudRenderingProperties(pcl::visualization::PCL_VISUALIZER_POINT_SIZE, 10, "clicked_points");
    55. //添加点索引号
    56. PointT position(current_point.x, current_point.y + 0.01, current_point.z);
    57. data->viewerPtr->addText3D(std::to_string(count), position, 0.1, 1,0,0);
    58. data->viewerPtr->resetCameraViewpoint();
    59. cout << current_point << endl;
    60. PointT convert_point = pcl::transformPoint(current_point, data->affine);
    61. data->clicked_points_3d_convert->points.push_back(convert_point);
    62. if (count == 6)
    63. {
    64. //方向包围盒OBB
    65. pcl::MomentOfInertiaEstimation feature_extractor;
    66. feature_extractor.setInputCloud(data->clicked_points_3d);
    67. feature_extractor.compute();
    68. pcl::PointXYZ min_point_OBB;
    69. pcl::PointXYZ max_point_OBB;
    70. pcl::PointXYZ position_OBB;
    71. Eigen::Matrix3f rotational_matrix_OBB;
    72. feature_extractor.getOBB(min_point_OBB, max_point_OBB, position_OBB, rotational_matrix_OBB);
    73. Eigen::Vector3f position(position_OBB.x, position_OBB.y, position_OBB.z);
    74. Eigen::Quaternionf quat(rotational_matrix_OBB);
    75. data->viewerPtr->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");
    76. data->viewerPtr->setShapeRenderingProperties(pcl::visualization::PCL_VISUALIZER_REPRESENTATION, pcl::visualization::PCL_VISUALIZER_REPRESENTATION_WIREFRAME, "OBB");
    77. feature_extractor.setInputCloud(data->clicked_points_3d_convert);
    78. feature_extractor.compute();
    79. feature_extractor.getOBB(min_point_OBB, max_point_OBB, position_OBB, rotational_matrix_OBB);
    80. Eigen::Vector3f positionConvert(position_OBB.x, position_OBB.y, position_OBB.z);
    81. Eigen::Quaternionf quatConvert(rotational_matrix_OBB);
    82. data->viewerPtr->addCube(positionConvert, quatConvert, max_point_OBB.x - min_point_OBB.x, max_point_OBB.y - min_point_OBB.y, max_point_OBB.z - min_point_OBB.z, "OBBConvert");
    83. data->viewerPtr->setShapeRenderingProperties(pcl::visualization::PCL_VISUALIZER_REPRESENTATION, pcl::visualization::PCL_VISUALIZER_REPRESENTATION_WIREFRAME, "OBBConvert");
    84. }
    85. }
    86. int main()
    87. {
    88. PointCloud::Ptr cloud_src(new PointCloud);
    89. PointCloud::Ptr cloud_tgt(new PointCloud);
    90. pcl::io::loadPCDFile("D:\\PCL\\data-master\\segmentation\\mOSD\\learn\\learn5.pcd", *cloud_src);
    91. Eigen::Matrix4f transform_1 = Eigen::Matrix4f::Identity();//定义绕X轴的旋转矩阵,并初始化为单位阵
    92. float theta = M_PI / 4; // The angle of rotation in radians
    93. transform_1(0, 0) = std::cos(theta);
    94. transform_1(0, 1) = -sin(theta);
    95. transform_1(1, 0) = sin(theta);
    96. transform_1(1, 1) = std::cos(theta);
    97. transform_1(0, 3) = 0.7f;
    98. transform_1(1, 3) = 0.6f;
    99. transform_1(2, 3) = 1.2f;
    100. pcl::transformPointCloud(*cloud_src, *cloud_tgt, transform_1);
    101. std::cout << "cloud_src size: " << cloud_src->size() << std::endl;
    102. std::cout << "cloud_target size: " << cloud_tgt->size() << std::endl;
    103. pcl::visualization::PCLVisualizer* p;
    104. p = new pcl::visualization::PCLVisualizer("view");
    105. cloud_mutex.lock(); // for not overwriting the point cloud
    106. PointCloudColorHandlerCustom src_h(cloud_src, 0, 0, 255);
    107. PointCloudColorHandlerCustom tgt_h(cloud_tgt, 0, 255, 0);
    108. p->setBackgroundColor(0.5, 0.5, 0.1, 0); // 设置背景为深灰
    109. p->addPointCloud(cloud_src, src_h, "vp1_src");
    110. p->addPointCloud(cloud_tgt, tgt_h, "vp1_target");
    111. struct callback_args cb_args;
    112. PointCloud::Ptr clicked_points_3d(new PointCloud);
    113. PointCloud::Ptr clicked_points_3d_convert(new PointCloud);
    114. cb_args.clicked_points_3d = clicked_points_3d;
    115. cb_args.clicked_points_3d_convert = clicked_points_3d_convert;
    116. cb_args.viewerPtr = pcl::visualization::PCLVisualizer::Ptr(p);
    117. //cb_args.viewerPtr->addCoordinateSystem(0.5);
    118. PointT position(0, 0, 0);
    119. PointT positionx(1, 0, 0);
    120. PointT positiony(0, 1, 0);
    121. PointT positionz(0, 0, 1);
    122. cb_args.viewerPtr->addArrow(positionx, position,0,0,1,false, "x");
    123. cb_args.viewerPtr->addArrow(positiony, position, 0,1, 0,false, "y");
    124. cb_args.viewerPtr->addArrow(positionz, position, 1, 0, 0,false, "z");
    125. cb_args.viewerPtr->addText3D("x", positionx, 0.2, 0, 0, 1,"x1");
    126. cb_args.viewerPtr->addText3D("y", positiony, 0.2, 0, 1, 0,"y1");
    127. Eigen::Affine3f affine(transform_1);
    128. cb_args.affine = affine;
    129. p->registerPointPickingCallback(pointPick_callback, (void*)&cb_args);
    130. cout << "->Shift + 鼠标左键选点,按 ‘Q’结束选点" << endl;
    131. p->spin();
    132. cout << "->选点结束" << endl;
    133. PointT conver_point = pcl::transformPoint(cb_args.clicked_points_3d->points[0], affine);
    134. std::cout << "use the affine to covert the point: " << std::endl;
    135. std::cout << conver_point << std::endl;
    136. cloud_mutex.unlock();
    137. while (!p->wasStopped())
    138. {
    139. p->spinOnce(100);
    140. boost::this_thread::sleep(boost::posix_time::microseconds(100000));
    141. }
    142. return (0);
    143. }

    执行效果如下:

     可看到,此段代码实现了ROI区域跟随点云变化的功能。

  • 相关阅读:
    ffmpeg5及以上-s和像素格式转换 画屏问题
    “华为杯”第十六届中国研究生数学建模竞赛-C题:视觉情报信息分析
    loj 10078 / 一本通 1500 / 洛谷 P5764【最短路】【dfs枚举排列】
    02Nacos和Feign及Gateway配置
    JVM类加载器(详解)
    STM32F103ZET6【HAL开发】STM32CUBEMX------3.3测量PWM的频率和占空比
    都2022年了,Python Web框架你不会只知道Django和Flask吧?
    新华三路由器+华为交换机,实现华为交换机指定端口访问外网
    git设置代理
    Java 异常处理机制
  • 原文地址:https://blog.csdn.net/jiugeshao/article/details/127835172