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点云

这里自定义了一个旋转平移矩阵(将点云通过这个变换为另外一个点云),详细见如下代码:
- #include
// for pcl::make_shared - #include
- #include
- #include
- #include
-
- #include
- #include
-
- #include
-
- #include
- #include
- #include
-
- #include
-
-
- #include
-
- using pcl::visualization::PointCloudColorHandlerGenericField;
- using pcl::visualization::PointCloudColorHandlerCustom;
-
- //convenient typedefs
- typedef pcl::PointXYZ PointT;
- typedef pcl::PointCloud
PointCloud; - typedef pcl::PointNormal PointNormalT;
- typedef pcl::PointCloud
PointCloudWithNormals; -
- int main()
- {
- PointCloud::Ptr cloud_src(new PointCloud);
- PointCloud::Ptr cloud_tgt(new PointCloud);
-
- pcl::io::loadPCDFile("D:\\PCL\\data-master\\segmentation\\mOSD\\learn\\learn5.pcd", *cloud_src);
-
- Eigen::Matrix4f transform_1 = Eigen::Matrix4f::Identity();//定义绕X轴的旋转矩阵,并初始化为单位阵
-
- float theta = M_PI / 4; // The angle of rotation in radians
- transform_1(0, 0) = std::cos(theta);
- transform_1(0, 1) = -sin(theta);
- transform_1(1, 0) = sin(theta);
- transform_1(1, 1) = std::cos(theta);
-
- transform_1(0, 3) = 0.7f;
- transform_1(1, 3) = 0.6f;
- transform_1(2, 3) = 1.2f;
-
- pcl::transformPointCloud(*cloud_src, *cloud_tgt, transform_1);
-
- std::cout << "cloud_src size: " << cloud_src->size() << std::endl;
- std::cout << "cloud_target size: " << cloud_tgt->size() << std::endl;
-
- pcl::visualization::PCLVisualizer* p;
- int vp_1, vp_2;
-
- p = new pcl::visualization::PCLVisualizer("view");
-
- PointCloudColorHandlerCustom
src_h(cloud_src, 255, 0, 0) ; - PointCloudColorHandlerCustom
tgt_h(cloud_tgt, 0, 255, 0) ; -
- p->addPointCloud(cloud_src, src_h, "vp1_src");
- p->addPointCloud(cloud_tgt, tgt_h, "vp1_target");
-
-
- p->spin();
-
- return (0);
- }
运行结果如下:

接下来在变换前的点云数据上点选一个ROI区域,代码如下:
- #include
// for pcl::make_shared - #include
- #include
- #include
- #include
-
- #include
- #include
-
- #include
-
- #include
- #include
- #include
-
- #include
-
- #include
- #include
- #include
- #include
-
- #include
-
- using pcl::visualization::PointCloudColorHandlerGenericField;
- using pcl::visualization::PointCloudColorHandlerCustom;
-
- //convenient typedefs
- typedef pcl::PointXYZ PointT;
- typedef pcl::PointCloud
PointCloud; - typedef pcl::PointNormal PointNormalT;
- typedef pcl::PointCloud
PointCloudWithNormals; -
- //Mutex
- boost::mutex cloud_mutex;
-
- struct callback_args
- {
- PointCloud::Ptr clicked_points_3d;
- pcl::visualization::PCLVisualizer::Ptr viewerPtr;
- };
-
- //点选函数
- void pointPick_callback(const pcl::visualization::PointPickingEvent& event, void* args)
- {
- struct callback_args* data = (struct callback_args*)args;
- if (event.getPointIndex() == -1)
- {
- return;
- }
-
- //提取当前点
- PointT current_point;
- event.getPoint(current_point.x, current_point.y, current_point.z);
- data->clicked_points_3d->points.push_back(current_point);
-
- //显示当前点
- pcl::visualization::PointCloudColorHandlerCustom
red(data->clicked_points_3d, 255, 0, 0) ; - data->viewerPtr->removePointCloud("clicked_points");
- data->viewerPtr->addPointCloud(data->clicked_points_3d, red, "clicked_points");
- data->viewerPtr->setPointCloudRenderingProperties(pcl::visualization::PCL_VISUALIZER_POINT_SIZE, 10, "clicked_points");
- cout << current_point << endl;
- }
-
-
- int main()
- {
- PointCloud::Ptr cloud_src(new PointCloud);
- PointCloud::Ptr cloud_tgt(new PointCloud);
-
- pcl::io::loadPCDFile("D:\\PCL\\data-master\\segmentation\\mOSD\\learn\\learn5.pcd", *cloud_src);
-
- Eigen::Matrix4f transform_1 = Eigen::Matrix4f::Identity();//定义绕X轴的旋转矩阵,并初始化为单位阵
-
- float theta = M_PI / 4; // The angle of rotation in radians
- transform_1(0, 0) = std::cos(theta);
- transform_1(0, 1) = -sin(theta);
- transform_1(1, 0) = sin(theta);
- transform_1(1, 1) = std::cos(theta);
-
- transform_1(0, 3) = 0.7f;
- transform_1(1, 3) = 0.6f;
- transform_1(2, 3) = 1.2f;
-
- pcl::transformPointCloud(*cloud_src, *cloud_tgt, transform_1);
-
- std::cout << "cloud_src size: " << cloud_src->size() << std::endl;
- std::cout << "cloud_target size: " << cloud_tgt->size() << std::endl;
-
-
-
- pcl::visualization::PCLVisualizer* p;
-
- p = new pcl::visualization::PCLVisualizer("view");
-
- cloud_mutex.lock(); // for not overwriting the point cloud
-
- PointCloudColorHandlerCustom
src_h(cloud_src, 0, 0, 255) ; - PointCloudColorHandlerCustom
tgt_h(cloud_tgt, 0, 255, 0) ; -
- p->setBackgroundColor(0.5, 0.5, 0.1, 0); // 设置背景为深灰
-
- p->addPointCloud(cloud_src, src_h, "vp1_src");
- p->addPointCloud(cloud_tgt, tgt_h, "vp1_target");
-
- struct callback_args cb_args;
- PointCloud::Ptr clicked_points_3d(new PointCloud);
-
- cb_args.clicked_points_3d = clicked_points_3d;
- cb_args.viewerPtr = pcl::visualization::PCLVisualizer::Ptr(p);
- p->registerPointPickingCallback(pointPick_callback, (void*)&cb_args);
-
- cout << "->Shift + 鼠标左键选点,按 ‘Q’结束选点" << endl;
-
- p->spin();
-
- cout << "->选点结束" << endl;
-
- Eigen::Affine3f affine(transform_1);
-
- PointT conver_point = pcl::transformPoint(cb_args.clicked_points_3d->points[0], affine);
- std::cout << "use the affine to covert the point: " << std::endl;
- std::cout << conver_point << std::endl;
-
- cloud_mutex.unlock();
-
- while (!p->wasStopped())
- {
- p->spinOnce(100);
- boost::this_thread::sleep(boost::posix_time::microseconds(100000));
- }
-
- return (0);
- }
运行程序,可看到如下先点选了蓝色点云上的一个角点,又鼠标点选了绿色点云上对应位置处的一角点。这个两个点云的点同时也在点云上show出来了。

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

代码如下,在第一个点云上可以通过鼠标点选ROI区域,完毕后会在第二个点云上会产生一个ROI区域,可看到是跟随目标变化的。
- #include
// for pcl::make_shared - #include
- #include
- #include
- #include
-
- #include
- #include
-
- #include
-
- #include
- #include
- #include
-
- #include
-
- #include
- #include
- #include
- #include
-
- #include
-
- #include
-
- using pcl::visualization::PointCloudColorHandlerGenericField;
- using pcl::visualization::PointCloudColorHandlerCustom;
-
- //convenient typedefs
- typedef pcl::PointXYZ PointT;
- typedef pcl::PointCloud
PointCloud; - typedef pcl::PointNormal PointNormalT;
- typedef pcl::PointCloud
PointCloudWithNormals; -
- pcl::PointCloud
::Ptr points; -
- //Mutex
- boost::mutex cloud_mutex;
- int count = 0;
-
-
-
- struct callback_args
- {
- PointCloud::Ptr clicked_points_3d;
- PointCloud::Ptr clicked_points_3d_convert;
- pcl::visualization::PCLVisualizer::Ptr viewerPtr;
- Eigen::Affine3f affine;
- };
-
- //点选函数
- void pointPick_callback(const pcl::visualization::PointPickingEvent& event, void* args)
- {
- count++;
-
- struct callback_args* data = (struct callback_args*)args;
- if (event.getPointIndex() == -1)
- {
- return;
- }
-
- //提取当前点
- PointT current_point;
- event.getPoint(current_point.x, current_point.y, current_point.z);
- data->clicked_points_3d->points.push_back(current_point);
-
- //显示当前点
- pcl::visualization::PointCloudColorHandlerCustom
red(data->clicked_points_3d, 255, 0, 0) ; - data->viewerPtr->removePointCloud("clicked_points");
- data->viewerPtr->addPointCloud(data->clicked_points_3d, red, "clicked_points");
- data->viewerPtr->setPointCloudRenderingProperties(pcl::visualization::PCL_VISUALIZER_POINT_SIZE, 10, "clicked_points");
-
- //添加点索引号
- PointT position(current_point.x, current_point.y + 0.01, current_point.z);
- data->viewerPtr->addText3D(std::to_string(count), position, 0.1, 1,0,0);
-
- data->viewerPtr->resetCameraViewpoint();
-
-
- cout << current_point << endl;
- PointT convert_point = pcl::transformPoint(current_point, data->affine);
- data->clicked_points_3d_convert->points.push_back(convert_point);
-
- if (count == 6)
- {
- //方向包围盒OBB
- pcl::MomentOfInertiaEstimation
feature_extractor; - feature_extractor.setInputCloud(data->clicked_points_3d);
- feature_extractor.compute();
-
- pcl::PointXYZ min_point_OBB;
- pcl::PointXYZ max_point_OBB;
- pcl::PointXYZ position_OBB;
- Eigen::Matrix3f rotational_matrix_OBB;
- feature_extractor.getOBB(min_point_OBB, max_point_OBB, position_OBB, rotational_matrix_OBB);
-
- Eigen::Vector3f position(position_OBB.x, position_OBB.y, position_OBB.z);
- Eigen::Quaternionf quat(rotational_matrix_OBB);
- 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");
- data->viewerPtr->setShapeRenderingProperties(pcl::visualization::PCL_VISUALIZER_REPRESENTATION, pcl::visualization::PCL_VISUALIZER_REPRESENTATION_WIREFRAME, "OBB");
-
-
- feature_extractor.setInputCloud(data->clicked_points_3d_convert);
- feature_extractor.compute();
-
- feature_extractor.getOBB(min_point_OBB, max_point_OBB, position_OBB, rotational_matrix_OBB);
-
- Eigen::Vector3f positionConvert(position_OBB.x, position_OBB.y, position_OBB.z);
- Eigen::Quaternionf quatConvert(rotational_matrix_OBB);
-
- 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");
- data->viewerPtr->setShapeRenderingProperties(pcl::visualization::PCL_VISUALIZER_REPRESENTATION, pcl::visualization::PCL_VISUALIZER_REPRESENTATION_WIREFRAME, "OBBConvert");
- }
- }
-
-
- int main()
- {
- PointCloud::Ptr cloud_src(new PointCloud);
- PointCloud::Ptr cloud_tgt(new PointCloud);
-
- pcl::io::loadPCDFile("D:\\PCL\\data-master\\segmentation\\mOSD\\learn\\learn5.pcd", *cloud_src);
-
- Eigen::Matrix4f transform_1 = Eigen::Matrix4f::Identity();//定义绕X轴的旋转矩阵,并初始化为单位阵
-
- float theta = M_PI / 4; // The angle of rotation in radians
- transform_1(0, 0) = std::cos(theta);
- transform_1(0, 1) = -sin(theta);
- transform_1(1, 0) = sin(theta);
- transform_1(1, 1) = std::cos(theta);
-
- transform_1(0, 3) = 0.7f;
- transform_1(1, 3) = 0.6f;
- transform_1(2, 3) = 1.2f;
-
- pcl::transformPointCloud(*cloud_src, *cloud_tgt, transform_1);
-
- std::cout << "cloud_src size: " << cloud_src->size() << std::endl;
- std::cout << "cloud_target size: " << cloud_tgt->size() << std::endl;
-
-
-
- pcl::visualization::PCLVisualizer* p;
-
- p = new pcl::visualization::PCLVisualizer("view");
-
- cloud_mutex.lock(); // for not overwriting the point cloud
-
- PointCloudColorHandlerCustom
src_h(cloud_src, 0, 0, 255) ; - PointCloudColorHandlerCustom
tgt_h(cloud_tgt, 0, 255, 0) ; -
- p->setBackgroundColor(0.5, 0.5, 0.1, 0); // 设置背景为深灰
-
- p->addPointCloud(cloud_src, src_h, "vp1_src");
- p->addPointCloud(cloud_tgt, tgt_h, "vp1_target");
-
- struct callback_args cb_args;
- PointCloud::Ptr clicked_points_3d(new PointCloud);
- PointCloud::Ptr clicked_points_3d_convert(new PointCloud);
-
- cb_args.clicked_points_3d = clicked_points_3d;
- cb_args.clicked_points_3d_convert = clicked_points_3d_convert;
-
- cb_args.viewerPtr = pcl::visualization::PCLVisualizer::Ptr(p);
- //cb_args.viewerPtr->addCoordinateSystem(0.5);
- PointT position(0, 0, 0);
- PointT positionx(1, 0, 0);
- PointT positiony(0, 1, 0);
- PointT positionz(0, 0, 1);
- cb_args.viewerPtr->addArrow
(positionx, position,0,0,1,false, "x"); - cb_args.viewerPtr->addArrow
(positiony, position, 0,1, 0,false, "y"); - cb_args.viewerPtr->addArrow
(positionz, position, 1, 0, 0,false, "z"); -
- cb_args.viewerPtr->addText3D("x", positionx, 0.2, 0, 0, 1,"x1");
- cb_args.viewerPtr->addText3D("y", positiony, 0.2, 0, 1, 0,"y1");
-
-
- Eigen::Affine3f affine(transform_1);
- cb_args.affine = affine;
-
- p->registerPointPickingCallback(pointPick_callback, (void*)&cb_args);
-
- cout << "->Shift + 鼠标左键选点,按 ‘Q’结束选点" << endl;
-
- p->spin();
-
- cout << "->选点结束" << endl;
-
-
-
- PointT conver_point = pcl::transformPoint(cb_args.clicked_points_3d->points[0], affine);
- std::cout << "use the affine to covert the point: " << std::endl;
- std::cout << conver_point << std::endl;
-
- cloud_mutex.unlock();
-
- while (!p->wasStopped())
- {
- p->spinOnce(100);
- boost::this_thread::sleep(boost::posix_time::microseconds(100000));
- }
-
- return (0);
- }
执行效果如下:

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