Pointpillars三维点云实时检测

这篇具有很好参考价值的文章主要介绍了Pointpillars三维点云实时检测。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

目录

一、项目方案

二、项目准备工作

1.安装并配置好Openpcdet的环境

2.安装好ROS melodic

三、项目工作空间创建及代码配置

四、具体代码修改与讲解

launch/pointpillars.launch的修改

launch/pointpillars.rviz的修改

五、实时检测效果展示

六、项目思考以及未解决的问题

七、Reference


一、项目方案

ROS的通讯机制使得它在机器人和无人驾驶领域应用十分广泛。所以本项目通讯都在ROS里进行。

1.激光雷达或者相机通过ROS发送点云信息

2.获得的点云msg消息通过转换送入pointpillars目标检测框架,检测完毕获得检测框通过ROS消息发送出去。

3.在ROS的rviz里面对这些消息进行显示。

二、项目准备工作

1.安装并配置好Openpcdet的环境

使用OpenPcdet框架里面的pointpillars代码进行,因为这个框架对于三维目标检测算法的封装集成度很高,方便我们进行使用。

2.安装好ROS melodic

本项目是基于ROS进行的,所以要提前安装好,其他的ROS版本也可

三、项目工作空间创建及代码配置

mkdir -p ~/pointpillars_ros/src
cd pointpillars_ros/src

下载这个包,这个包是某个大佬写的,后面有参考链接。

git clone https://github.com/BIT-DYN/pointpillars_ros
cd ..

 进入openpcdet的conda环境,然后安装几个库,jsk-recognition-msg这个库里面的消息主要是存放检测框的。具体可以看这个链接https://blog.csdn.net/leesanity/article/details/123137541

# 进入到搭建好的openpcdet环境
conda activate pcdet
pip install --user rospkg catkin_pkg
pip install pyquaternion

sudo apt-get install ros-melodic-pcl-ros
sudo apt-get install ros-melodic-jsk-recognition-msg
sudo apt-get install ros-melodic-jsk-rviz-plugins
catkin_make

然后再把Openpcdet里面的相关文件移进来,放到src/pointpillars/tools下面openpcdet实时,深度学习,人工智能,目标检测

 这里可以改一下demo.py里面配置文件和预训练模型,然后放入数据检查一下openpcdet移植过来还能跑通不。

四、具体代码修改与讲解

先修改ros.py,大家可以先用下面的ros.py代码替换掉原先的。代码如下:

#!/usr/bin/env python3

import rospy

from sensor_msgs.msg import PointCloud2,PointField

import sensor_msgs.point_cloud2 as pc2
from std_msgs.msg import Header
from jsk_recognition_msgs.msg import BoundingBox, BoundingBoxArray

import time
import numpy as np
from pyquaternion import Quaternion

import argparse
import glob
from pathlib import Path

import numpy as np
import torch
import scipy.linalg as linalg

import sys
sys.path.append("/home/wangchen/pointpillars_ros/src/pointpillars_ros")

from pcdet.config import cfg, cfg_from_yaml_file
from pcdet.datasets import DatasetTemplate
from pcdet.models import build_network, load_data_to_gpu
from pcdet.utils import common_utils

class DemoDataset(DatasetTemplate):
    def __init__(self, dataset_cfg, class_names, training=True, root_path=None, logger=None, ext='.bin'):
        """
        Args:
            root_path: 根目录
            dataset_cfg: 数据集配置
            class_names: 类别名称
            training: 训练模式
            logger: 日志
            ext: 扩展名
        """
        super().__init__(
            dataset_cfg=dataset_cfg, class_names=class_names, training=training, root_path=root_path, logger=logger
        )



class Pointpillars_ROS:
    def __init__(self):
        config_path, ckpt_path = self.init_ros()
        self.init_pointpillars(config_path, ckpt_path)


    def init_ros(self):
        """ Initialize ros parameters """
        config_path = rospy.get_param("/config_path", "/home/wangchen/pointpillars_ros/src/pointpillars_ros/tools/cfgs/kitti_models/pointpillar.yaml")
        ckpt_path = rospy.get_param("/ckpt_path", "/home/wangchen/pointpillars_ros/src/pointpillars_ros/tools/pointpillar_7728.pth")
        # # subscriber
        # self.sub_velo = rospy.Subscriber("/kitti/velo/pointcloud", PointCloud2, self.lidar_callback, queue_size=1,
        #                                  buff_size=2 ** 12)
        #
        # # publisher
        # self.sub_velo = rospy.Publisher("/modified", PointCloud2, queue_size=1)
        # self.pub_bbox = rospy.Publisher("/detections", BoundingBoxArray, queue_size=10)
        return config_path, ckpt_path


    def init_pointpillars(self, config_path, ckpt_path):
        """ Initialize second model """
        logger = common_utils.create_logger() # 创建日志
        logger.info('-----------------Quick Demo of Pointpillars-------------------------')
        cfg_from_yaml_file(config_path, cfg)  # 加载配置文件

        self.demo_dataset = DemoDataset(
            dataset_cfg=cfg.DATA_CONFIG, class_names=cfg.CLASS_NAMES, training=False,
            ext='.bin', logger=logger
        )
        self.model = build_network(model_cfg=cfg.MODEL, num_class=len(cfg.CLASS_NAMES), dataset=self.demo_dataset)
        # 加载权重文件
        self.model.load_params_from_file(filename=ckpt_path, logger=logger, to_cpu=True)
        self.model.cuda() # 将网络放到GPU上
        self.model.eval() # 开启评估模式


    def rotate_mat(self, axis, radian):
        rot_matrix = linalg.expm(np.cross(np.eye(3), axis / linalg.norm(axis) * radian))
        return rot_matrix


    def lidar_callback(self, msg):
        """ Captures pointcloud data and feed into second model for inference """
        pcl_msg = pc2.read_points(msg, field_names = ("x", "y", "z", "intensity"), skip_nans=True)
        #这里的field_names可以不要,不要就是把数据全部读取进来。也可以用field_names = ("x", "y", "z")这个只读xyz坐标
        #得到的pcl_msg是一个generator生成器,如果要一次获得全部的点,需要转成list
        np_p = np.array(list(pcl_msg), dtype=np.float32)
        #print(np_p.shape)
        # 旋转轴
        #rand_axis = [0,1,0]
        #旋转角度
        #yaw = 0.1047
        #yaw = 0.0
        #返回旋转矩阵
        #rot_matrix = self.rotate_mat(rand_axis, yaw)
        #np_p_rot = np.dot(rot_matrix, np_p[:,:3].T).T

        # convert to xyzi point cloud
        x = np_p[:, 0].reshape(-1)
        #print(np.max(x),np.min(x))
        y = np_p[:, 1].reshape(-1)
        z = np_p[:, 2].reshape(-1)
        if np_p.shape[1] == 4: # if intensity field exists
            i = np_p[:, 3].reshape(-1)
        else:
            i = np.zeros((np_p.shape[0], 1)).reshape(-1)
        points = np.stack((x, y, z, i)).T
        # 组装数组字典
        input_dict = {
            'frame_id': msg.header.frame_id,
            'points': points
        }
        data_dict = self.demo_dataset.prepare_data(data_dict=input_dict) # 数据预处理
        data_dict = self.demo_dataset.collate_batch([data_dict])
        load_data_to_gpu(data_dict) # 将数据放到GPU上
        pred_dicts, _ = self.model.forward(data_dict) # 模型前向传播
        scores = pred_dicts[0]['pred_scores'].detach().cpu().numpy()
        mask = scores > 0.5
        scores = scores[mask]
        boxes_lidar = pred_dicts[0]['pred_boxes'][mask].detach().cpu().numpy()
        label = pred_dicts[0]['pred_labels'][mask].detach().cpu().numpy()
        num_detections = boxes_lidar.shape[0]

        arr_bbox = BoundingBoxArray()
        for i in range(num_detections):
            bbox = BoundingBox()

            bbox.header.frame_id = msg.header.frame_id
            bbox.header.stamp = rospy.Time.now()
            bbox.pose.position.x = float(boxes_lidar[i][0])
            bbox.pose.position.y = float(boxes_lidar[i][1])
            bbox.pose.position.z = float(boxes_lidar[i][2]) #+ float(boxes_lidar[i][5]) / 2
            bbox.dimensions.x = float(boxes_lidar[i][3])  # width
            bbox.dimensions.y = float(boxes_lidar[i][4])  # length
            bbox.dimensions.z = float(boxes_lidar[i][5])  # height
            q = Quaternion(axis=(0, 0, 1), radians=float(boxes_lidar[i][6]))
            bbox.pose.orientation.x = q.x
            bbox.pose.orientation.y = q.y
            bbox.pose.orientation.z = q.z
            bbox.pose.orientation.w = q.w
            bbox.value = scores[i]
            bbox.label = label[i]

            arr_bbox.boxes.append(bbox)

        arr_bbox.header.frame_id = msg.header.frame_id
        #arr_bbox.header.stamp = rospy.Time.now()

        if len(arr_bbox.boxes) is not 0:
            pub_bbox.publish(arr_bbox)
            self.publish_test(points, msg.header.frame_id)

    def publish_test(self, cloud, frame_id):
        header = Header()
        header.stamp = rospy.Time()
        header.frame_id = frame_id
        fields = [PointField('x', 0, PointField.FLOAT32, 1),
                  PointField('y', 4, PointField.FLOAT32, 1),
                  PointField('z', 8, PointField.FLOAT32, 1),
                  PointField('intensity', 12, PointField.FLOAT32, 1)]  # ,PointField('label', 16, PointField.FLOAT32, 1)
        #creat_cloud不像read,他必须要有fields,而且field定义有两种。一个是上面的,一个是下面的fields=_make_point_field(4)
        msg_segment = pc2.create_cloud(header = header,fields=fields,points = cloud)

        pub_velo.publish(msg_segment)
        #pub_image.publish(image_msg)


def _make_point_field(num_field):
    msg_pf1 = pc2.PointField()
    msg_pf1.name = np.str_('x')
    msg_pf1.offset = np.uint32(0)
    msg_pf1.datatype = np.uint8(7)
    msg_pf1.count = np.uint32(1)

    msg_pf2 = pc2.PointField()
    msg_pf2.name = np.str_('y')
    msg_pf2.offset = np.uint32(4)
    msg_pf2.datatype = np.uint8(7)
    msg_pf2.count = np.uint32(1)

    msg_pf3 = pc2.PointField()
    msg_pf3.name = np.str_('z')
    msg_pf3.offset = np.uint32(8)
    msg_pf3.datatype = np.uint8(7)
    msg_pf3.count = np.uint32(1)

    msg_pf4 = pc2.PointField()
    msg_pf4.name = np.str_('intensity')
    msg_pf4.offset = np.uint32(16)
    msg_pf4.datatype = np.uint8(7)
    msg_pf4.count = np.uint32(1)

    if num_field == 4:
        return [msg_pf1, msg_pf2, msg_pf3, msg_pf4]

    msg_pf5 = pc2.PointField()
    msg_pf5.name = np.str_('label')
    msg_pf5.offset = np.uint32(20)
    msg_pf5.datatype = np.uint8(4)
    msg_pf5.count = np.uint32(1)

    return [msg_pf1, msg_pf2, msg_pf3, msg_pf4, msg_pf5]
if __name__ == '__main__':
    global sec
    sec = Pointpillars_ROS()

    rospy.init_node('pointpillars_ros_node', anonymous=True)

    # subscriber

    sub_velo = rospy.Subscriber("/kitti/velo/pointcloud", PointCloud2, sec.lidar_callback, queue_size=1,
                                    buff_size=2 ** 12)


    # publisher
    pub_velo = rospy.Publisher("/modified", PointCloud2, queue_size=1)
    pub_bbox = rospy.Publisher("/detections", BoundingBoxArray, queue_size=10)

    try:
        rospy.spin()
    except KeyboardInterrupt:
        del sec
        print("Shutting down")

替换完之后,大家要改的是24行,56 ,57行的预训练权重和config文件,改成你自己的路径即可。如果是你自己的雷达或相机219行换成你自己的话题名

launch/pointpillars.launch的修改

 <node pkg="rosbag" type="play" name="player" output="log" args="-l /media/ubuntu/ximing/dataset/ros_kitti/bag/2011_10_03/kitti_2011_10_03_drive_0027_synced.bag" />

把这个里面的ROSBAG路径改一下,改成你自己的就行。

这里附上一个ROSBAG包制作的链接https://blog.csdn.net/FSKEps/article/details/90345566

 这个链接里面需要下载的包在我百度网盘里,链接: https://pan.baidu.com/s/1EtG_Z8jujW77bU9o_ZoduQ提取码: sfiw

launch/pointpillars.rviz的修改

这个里面主要把Topic话题改一下,一个图像,一个点云,那个modified不改

Topic: /kitti/velo/pointcloud

Image Topic: /kitti/camera_color_left/image_raw

这两个话题是kitti的ROSbag包的话题,如果是自己的激光雷达要修改这两个话题。

还有一处如果是自己的雷达或相机也要修改。

Fixed Frame: velo_link,这里如果是自己的也要改。指的RVIZ里面的基准坐标系

五、实时检测效果展示

conda activate pcdet
source ~/pointpillars_ros/devel/setup.bash
roslaunch pointpillars_ros pointpillars.launch

可能会卡顿,打开RVIZ之后等一分钟。

openpcdet实时,深度学习,人工智能,目标检测

具体动画效果看大佬的bilibili链接https://www.bilibili.com/video/BV1ce4y1D76o/

播放的时候点云换成modified,这时框与点云可以对上。如果不换对不上。

六、项目思考以及未解决的问题

首先是点云和检测框在RVIZ里面显示的问题,/kitti/velo/pointcloud这个是我们订阅的点云话题,送入pointpillars检测之后会耗费一段时间,这时检测出来的检测框和/kitti/velo/pointcloud的时间戳对不上,所以会导致RVIZ里面点云与框不对应。这时我们在检测完框之后,重新定义一个点云,把他的时间戳和检测框的对齐,再发布出来就是我们代码里的modified点云,所以modified点云与框可以对应,但此时图像是和/kitti/velo/pointcloud对应的,所以我的想法是同时也订阅一个图像信息,等检测完,创建一个新的modified图像再发布,让他们时间戳对齐,这样就可以解决了,但事实证明,这样尝试了一下还是对不齐,希望大家有想法的可以积极讨论一下,很期待和大家一起解决这个问题。

第二个问题就是大家用自己的相机或者雷达做实时检测显示,我这里也和一位博主讨论过,把点云图像换成自己相机的,还有RVIZ里面的launch文件的基准坐标系也要改成你自己的。但是在实际场景中检测出来的检测框乱飞。现在还在尝试解决,希望大家可以一起解决这个问题。目前就这么多,也希望大家可以把自己的想法和问题说出来,我们一起讨论,谢谢大家的参与。

关于自己数据实时检测已经实现了,自己数据检测时要注意两点:

1.坐标系一定要转换为openpcdet的统一坐标系。

2.自己雷达采集的intensity一定要置零之后再进行检测,不然检测框会乱飞。

七、Reference

https://blog.csdn.net/jiachang98/article/details/126106126?spm=1001.2014.3001.5501

https://blog.csdn.net/weixin_43807148/article/details/125867953文章来源地址https://www.toymoban.com/news/detail-787685.html

到了这里,关于Pointpillars三维点云实时检测的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 竞赛保研 多目标跟踪算法 实时检测 - opencv 深度学习 机器视觉

    🔥 优质竞赛项目系列,今天要分享的是 🚩 深度学习多目标跟踪 实时检测 该项目较为新颖,适合作为竞赛课题方向,学长非常推荐! 🥇学长这里给一个题目综合评分(每项满分5分) 难度系数:3分 工作量:3分 创新点:4分 🧿 更多资料, 项目分享: https://gitee.com/dancheng-sen

    2024年01月16日
    浏览(70)
  • OpenCV与AI深度学习 | 实战|OpenCV实时弯道检测(详细步骤+源码)

    本文来源公众号“ OpenCV与AI深度学习 ”,仅用于学术分享,侵权删,干货满满。 原文链接:实战|OpenCV实时弯道检测(详细步骤+源码) 本文主要介绍如何使用 Python 和 OpenCV实现一个 实时曲线道路检测系统 。     在任何驾驶场景中, 车道线 都是指示交通流量和车辆应行驶位

    2024年04月27日
    浏览(57)
  • 多目标跟踪算法 实时检测 - opencv 深度学习 机器视觉 计算机竞赛

    🔥 优质竞赛项目系列,今天要分享的是 🚩 深度学习多目标跟踪 实时检测 该项目较为新颖,适合作为竞赛课题方向,学长非常推荐! 🥇学长这里给一个题目综合评分(每项满分5分) 难度系数:3分 工作量:3分 创新点:4分 🧿 更多资料, 项目分享: https://gitee.com/dancheng-sen

    2024年02月05日
    浏览(70)
  • 互联网加竞赛 多目标跟踪算法 实时检测 - opencv 深度学习 机器视觉

    🔥 优质竞赛项目系列,今天要分享的是 🚩 深度学习多目标跟踪 实时检测 该项目较为新颖,适合作为竞赛课题方向,学长非常推荐! 🥇学长这里给一个题目综合评分(每项满分5分) 难度系数:3分 工作量:3分 创新点:4分 🧿 更多资料, 项目分享: https://gitee.com/dancheng-sen

    2024年02月19日
    浏览(52)
  • 深度学习||YOLO(You Only Look Once)深度学习的实时目标检测算法(YOLOv1~YOLOv5)

    目录 YOLOv1: YOLOv2: YOLOv3: YOLOv4: YOLOv5: 总结: YOLO(You Only Look Once)是一系列基于深度学习的实时目标检测算法。 自从2015年首次被提出以来,YOLO系列不断发展,推出了多个版本,包括YOLOv1, YOLOv2, YOLOv3, YOLOv4, 和YOLOv5等。下面是对YOLO系列的详解: 提出时间 : 2015年。 主要贡献 :

    2024年02月20日
    浏览(58)
  • 毕业设计:python人脸识别系统 实时检测 深度学习 Dlib库 大数据 毕业设计(源码)✅

    🍅 大家好,今天给大家分享一个Python项目,感兴趣的可以先收藏起来,点赞、关注不迷路! 🍅 大家在毕设选题,项目以及论文编写等相关问题都可以给我留言咨询,希望帮助同学们顺利毕业 。 技术栈: Python语言、pyqt5图形界面、opencv、ResNet深度卷积神经网络、Dlib库 系统

    2024年02月20日
    浏览(92)
  • 三维点云实时和离线生成二维栅格、三维栅格地图(附github)

    github: GitHub - goldqiu/Map_Conversion: 导航“前端”,将定位后的三维点云实时或离线三维到二维栅格化,并计算代价生成代价地图。 导航“前端”,将定位后的三维点云实时或离线三维到二维栅格化,并计算代价生成代价地图。 运行 效果 参数 文件介绍 输入输出 输入: 全局点

    2024年02月15日
    浏览(59)
  • Realsense D435i Yolov5目标检测实时获得目标三维位置信息

    - Colorimage: - Colorimage and depthimage: 1.一个可以运行YOLOv5的python环境 2.一个realsense相机和pyrealsense2库 在下面两个环境中测试成功 win10 python 3.8 Pytorch 1.10.2+gpu CUDA 11.3 NVIDIA GeForce MX150 ubuntu16.04 python 3.6 Pytorch 1.7.1+cpu 修改模型配置文件,以yolov5s为例。 如果使用自己训练的模型,需要进

    2024年02月04日
    浏览(63)
  • 目标检测算法之voxelNet与pointpillars对比

    点云目标检测目前发展历经VoxelNet、SECOND、PointPillars、PV-RCNN。 2017年苹果提出voxelnet,是最早的一篇将点云转成voxel体素进行3D目标检测的论文。 然后2018年重庆大学的一个研究生Yan Yan在自动驾驶公司主线科技实习的时候将voxelnet代码完善,提出了高效的spconv实现,并增加了数据

    2024年02月02日
    浏览(38)
  • OpenPCDet安装及其3D检测算法实现

    open-mmlab /OpenPCDet是一个简洁独立开源的适用于激光雷达3D目标检测的平台,支持多种基于深度学习的3D目标检测算法,可以使用开源数据集或者自制数据集进行训练测试。 github网址链接 cmake官网链接 cmake版本要大于等于1.13,不然后边的库的setup过程会报错。不要看网上的博客

    2024年02月02日
    浏览(42)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包