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 <pcl/memory.h> // for pcl::make_shared
#include <pcl/point_types.h>
#include <pcl/point_cloud.h>
#include <pcl/point_representation.h>
#include <pcl/io/pcd_io.h>
#include <pcl/filters/voxel_grid.h>
#include <pcl/filters/filter.h>
#include <pcl/features/normal_3d.h>
#include <pcl/registration/icp.h>
#include <pcl/registration/icp_nl.h>
#include <pcl/registration/transforms.h>
#include <pcl/visualization/pcl_visualizer.h>
#include <boost/thread/thread.hpp>
using pcl::visualization::PointCloudColorHandlerGenericField;
using pcl::visualization::PointCloudColorHandlerCustom;
//convenient typedefs
typedef pcl::PointXYZ PointT;
typedef pcl::PointCloud<PointT> PointCloud;
typedef pcl::PointNormal PointNormalT;
typedef pcl::PointCloud<PointNormalT> 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<PointT> src_h(cloud_src, 255, 0, 0);
PointCloudColorHandlerCustom<PointT> 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 <pcl/memory.h> // for pcl::make_shared
#include <pcl/point_types.h>
#include <pcl/point_cloud.h>
#include <pcl/point_representation.h>
#include <pcl/io/pcd_io.h>
#include <pcl/filters/voxel_grid.h>
#include <pcl/filters/filter.h>
#include <pcl/features/normal_3d.h>
#include <pcl/registration/icp.h>
#include <pcl/registration/icp_nl.h>
#include <pcl/registration/transforms.h>
#include <pcl/visualization/pcl_visualizer.h>
#include <pcl/sample_consensus/method_types.h>
#include <pcl/sample_consensus/model_types.h>
#include <pcl/segmentation/sac_segmentation.h>
#include <pcl/segmentation/extract_clusters.h>
#include <boost/thread/thread.hpp>
using pcl::visualization::PointCloudColorHandlerGenericField;
using pcl::visualization::PointCloudColorHandlerCustom;
//convenient typedefs
typedef pcl::PointXYZ PointT;
typedef pcl::PointCloud<PointT> PointCloud;
typedef pcl::PointNormal PointNormalT;
typedef pcl::PointCloud<PointNormalT> 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<PointT> 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<PointT> src_h(cloud_src, 0, 0, 255);
PointCloudColorHandlerCustom<PointT> 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区域,完毕后会在第二个点云上会产生一个ROI区域,可看到是跟随目标变化的。
#include <pcl/memory.h> // for pcl::make_shared
#include <pcl/point_types.h>
#include <pcl/point_cloud.h>
#include <pcl/point_representation.h>
#include <pcl/io/pcd_io.h>
#include <pcl/filters/voxel_grid.h>
#include <pcl/filters/filter.h>
#include <pcl/features/normal_3d.h>
#include <pcl/registration/icp.h>
#include <pcl/registration/icp_nl.h>
#include <pcl/registration/transforms.h>
#include <pcl/visualization/pcl_visualizer.h>
#include <pcl/sample_consensus/method_types.h>
#include <pcl/sample_consensus/model_types.h>
#include <pcl/segmentation/sac_segmentation.h>
#include <pcl/segmentation/extract_clusters.h>
#include <pcl/features/moment_of_inertia_estimation.h>
#include <boost/thread/thread.hpp>
using pcl::visualization::PointCloudColorHandlerGenericField;
using pcl::visualization::PointCloudColorHandlerCustom;
//convenient typedefs
typedef pcl::PointXYZ PointT;
typedef pcl::PointCloud<PointT> PointCloud;
typedef pcl::PointNormal PointNormalT;
typedef pcl::PointCloud<PointNormalT> PointCloudWithNormals;
pcl::PointCloud<PointT>::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<PointT> 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 <pcl::PointXYZ> 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<PointT> src_h(cloud_src, 0, 0, 255);
PointCloudColorHandlerCustom<PointT> 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<PointT,PointT>(positionx, position,0,0,1,false, "x");
cb_args.viewerPtr->addArrow<PointT, PointT>(positiony, position, 0,1, 0,false, "y");
cb_args.viewerPtr->addArrow<PointT, PointT>(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区域跟随点云变化的功能。
版权归原作者 竹叶青lvye 所有, 如有侵权,请联系我们删除。