三维目标检测:(二)用ROS获取传感器(Kinect DK)点云并滤波

前期工作

  • [ 1] 需要配置Clion

https://blog.csdn.net/weixin_38593194/article/details/85122716

  • [ 2] 创建ros工作空间和功能包

https://blog.csdn.net/weixin_44858747/article/details/109479414

  • [ 3] 安装kinectDK官方SDK ,和ros功能包

https://blog.csdn.net/qq_27399933/article/details/107356117

  • [ 4] 需要在cmakelists文件和package.xml文件中添加opencv、pcl等库
    cmakelists.txt

find_package(catkin REQUIRED COMPONENTS
cv_bridge
image_transport
pcl_conversions
pcl_ros
roscpp
rospy
std_msgs
message_generation
)
find_package( PCL REQUIRED COMPONENTS common io visualization )

catkin_package(INCLUDE_DIRS include
LIBRARIES object_detection
CATKIN_DEPENDS
roscpp std_msgs message_generation message_runtime
)
include_directories(
$ {catkin_INCLUDE_DIRS} $ {PCL_INCLUDE_DIRS}
)
link_directories($ {PCL_LIBRARY_DIRS})
add_definitions($ {PCL_DEFINITIONS})
include_directories("./include/")
add_executable(main src/main.cpp include/pointcloud_seg/pointcloud_seg.h src/pointcloud_seg.cpp) 这部分自己改一下
target_link_libraries(main ${catkin_LIBRARIES} ${PCL_LIBRARIES})

package.xml(有些可能用不到,但是能跑通)

<buildtool_depend>catkin</buildtool_depend>
<build_depend>cv_bridge</build_depend>
<build_depend>image_transport</build_depend>
<build_depend>pcl_conversions</build_depend>
<build_depend>pcl_ros</build_depend>
<build_depend>roscpp</build_depend>
<build_depend>sensor_msgs</build_depend>
<build_depend>std_msgs</build_depend>
<build_depend>libpcl-all-dev</build_depend>
<build_depend>message_generation</build_depend>
<build_export_depend>cv_bridge</build_export_depend>
<build_export_depend>image_transport</build_export_depend>
<build_export_depend>pcl_conversions</build_export_depend>
<build_export_depend>pcl_ros</build_export_depend>
<build_export_depend>roscpp</build_export_depend>
<build_export_depend>sensor_msgs</build_export_depend>
<build_export_depend>std_msgs</build_export_depend>
<build_export_depend>libpcl-all</build_export_depend>
<build_export_depend>message_generation</build_export_depend>
<exec_depend>cv_bridge</exec_depend>
<exec_depend>image_transport</exec_depend>
<exec_depend>pcl_conversions</exec_depend>
<exec_depend>pcl_ros</exec_depend>
<exec_depend>roscpp</exec_depend>
<exec_depend>sensor_msgs</exec_depend>
<exec_depend>std_msgs</exec_depend>
<exec_depend>libpcl-all</exec_depend>
<exec_depend>message_runtime</exec_depend>

首先连接摄像头,打开节点

$ roslaunch azure_kinect_ros_driver driver.launch

在ros中读取传感器点云

1.创建类

#include <ros/ros.h>
#include <string>
#include <iostream>
#include <image_transport/image_transport.h>
#include <pcl_ros/point_cloud.h>
#include <pcl/point_types.h>
#include <pcl/point_cloud.h>
#include <pcl_conversions/pcl_conversions.h>
#include <sensor_msgs/PointCloud2.h>
#include <cv_bridge/cv_bridge.h>

using namespace std;
using namespace ros;
using namespace pcl;
typedef pcl::PointXYZRGB PointType;
class pointcloud_seg
{
public:
    ros::Subscriber sub;
public:
    pointcloud_seg(ros::NodeHandle &n);
    void get_pointcloud_cb(const sensor_msgs::PointCloud2& cloud_msg);
    ~pointcloud_seg();
};
pointcloud_seg::pointcloud_seg(ros::NodeHandle &n)
{
    //用于接受点云的节点和发布点云的节点 接受官方ros包发出的点云节点/points2
    sub=n.subscribe("/points2",1,&pointcloud_seg::get_pointcloud_cb,this);
    //一会用于发布平面点,和平面之外的点,如果不发布进行平面提取等结果,不需要定义
    pub_plant=n.advertise<sensor_msgs::PointCloud2>("Plant",1000); //发布平面点
    pub_obj=n.advertise<sensor_msgs::PointCloud2>("Object",1000);   //发布平面外的点
}
//接受点云的回调函数
void pointcloud_seg::get_pointcloud_cb(const sensor_msgs::PointCloud2 &cloud_msg) {
    pcl::PointCloud<PointType>::Ptr cloud(new pcl::PointCloud<PointType>);
    //ros获取的点云是pointcloud2类型的点云,需要转换为pcl类型的点云
    pcl::fromROSMsg(cloud_msg,*cloud);
    //cloud就是获取到的转换为pcl::PointXYZRGB的点云
    //可以在这部分对点云进行处理,包括滤波等操作
}
pointcloud_seg::~pointcloud_seg()
{
}
int main(int argc, char **argv)
{
    // Initialize ROS
    ros::init(argc, argv, "pointcloud_seg");
    ros::NodeHandle n;
    //定义类
    pointcloud_seg seg(n);
    ros::spin();
    return 0;
}

对点云进行采样和滤波

1.进行XYZ方向的直通滤波,可以保证点云的X,Y,Z范围在我们想要的范围内
需要头文件

#include <pcl/filters/passthrough.h>

    ///进行X方向的范围限制,点云中的所有点的x都在-1m到+1米
    pcl::PointCloud<PointType>::Ptr cloudPtrx(new pcl::PointCloud<PointType>);
    pcl::PassThrough<PointType> px_filter;
    //input点云
    px_filter.setInputCloud(cloud_msg_xyz); // Pass filtered_cloud to the filter
    px_filter.setFilterFieldName("x"); // Set axis x
    px_filter.setFilterLimits(-1, 1); // Set limits min_value to max_value
    //output点云
    px_filter.filter(*cloudPtrx); // Restore output data in second_cloud
	
    // Perform the PassThrough Filter to the Y axis
    pcl::PointCloud<PointType>::Ptr cloudPtry(new pcl::PointCloud<PointType>);
    pcl::PassThrough<PointType> py_filter;
    py_filter.setInputCloud(cloudPtrx); // Pass filtered_cloud to the filter
    py_filter.setFilterFieldName("y"); // Set axis y
    py_filter.setFilterLimits(-1, 1); // Set limits min_value to max_value
    py_filter.filter(*cloudPtry); // Restore output data in second_cloud

    // Perform the PassThrough Filter to the Z axis
    pcl::PointCloud<PointType>::Ptr cloudPtrz(new pcl::PointCloud<PointType>);
    pcl::PassThrough<PointType> pz_filter;
    pz_filter.setInputCloud(cloudPtry); // Pass filtered_cloud to the filter
    pz_filter.setFilterFieldName("z"); // Set axis z
    pz_filter.setFilterLimits(0, 1.5); // Set limits min_value to max_value
    pz_filter.filter(*cloudPtrz); // Restore output data in second_cloud
}
//最后处理过的点云cloudPtrz      x属于【-1,1】,y属于【-1,1】,z属于【0,1.5】 单位为m

2.进行体素滤波,目的是进行下采样,控制点云的密度
需要头文件

#include <pcl/filters/voxel_grid.h>

 // Perform the VoxelGrid Filter
    pcl::PointCloud<PointType>::Ptr cloudPtrv(new pcl::PointCloud<PointType>);
    pcl::VoxelGrid<PointType> v_filter;
    v_filter.setInputCloud(cloudPtrz); // Pass raw_cloud to the filter
    //设置体素网格的大小,越大点越少
    v_filter.setLeafSize(0.01, 0.01,0.01); // Set leaf size
    v_filter.filter(*cloudPtrv); // Store output data in first_cloud

3.去除离群点
需要头文件

#include<pcl/filters/radius_outlier_removal.h>

    //离群点去除
    pcl::RadiusOutlierRemoval<PointType> pcFilter;  //创建滤波器对象
    pcl::PointCloud<PointType>::Ptr cloud_filtered(new pcl::PointCloud<PointType>);
    pcFilter.setInputCloud(cloudPtrv);             //设置待滤波的点云
    pcFilter.setRadiusSearch(0.8);               // 设置搜索半径
    pcFilter.setMinNeighborsInRadius(2);      // 设置一个内点最少的邻居数目
    pcFilter.filter(*cloud_filtered);        //滤波结果存储到cloud_filtered
//上面就是如果某个点周围0.8的圆弧内有2个点就不算离群点,可能聚类以后再用效果比较好

根据半径内的点数确定某个点是否为噪声点,但是我感觉效果不明显,半径太短会很慢,半径太大效果不好,准备换一种方法

可以输出滤波后的点云了

需要转换为pointcloud2类型的数据

        sensor_msgs::PointCloud2 output;//声明的输出的点云的格式
        pcl::toROSMsg(*cloud_filtered, output);//第一个参数是输入,后面的是输出
        pub_obj.publish(output);

ROS中pcl的的转换代码

https://blog.csdn.net/u010284636/article/details/79214841

查看点云

打开rviz查看 查看output

rviz

代码小白,欢迎大家批评指正。

  • 2
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值