物体分析 Object Analytics (OA) 是一个ros包,
支持实时物体检测定位和跟踪(realtime object detection, localization and tracking.)
使用 RGB-D 相机输入,提供物体分析服务,为开发者开发更高级的机器人高级特性应用,
例如智能壁障(intelligent collision avoidance),和语义SLAM(semantic SLAM).
订阅:
RGB-D 相机发布的点云消息[sensor_msgs::PointClould2](http://docs.ros.org/api/sensor_msgs/html/msg/PointCloud2.html)
发布话题到:
物体检测 [object detection](https://github.com/intel/object_msgs),
物体跟踪 [object tracking](https://github.com/intel/ros_object_analytics/tree/master/object_analytics_msgs),
物体3d定位 [object localization](https://github.com/intel/ros_object_analytics/object_analytics_msgs)
依赖 优秀的算法:
-
基于 图形处理器(GPU) 运行的目标检测 , ros_opencl_caffe, Yolo v2 model and OpenCL Caffe framework
-
基于 视觉处理器(VPU) 运行的目标检测 , ros_intel_movidius_ncs (devel branch), with MobileNet_SSD model and Caffe framework.
(Movidius神经计算棒,首个基于USB模式的深度学习推理工具和独立的人工智能(AI)加速器) 英特尔的子公司Movidius宣布推出Movidius Myriad X视觉处理器(VPU), 该处理器是一款低功耗SoC,主要用于基于视觉的设备的深度学习和AI算法加速,比如无人机、智能相机、VR/AR头盔。 就在不久前的上个月,Movidius还推出了基于Myriad 2芯片的神经计算棒Movidius Neural Compute Stick。
ROS packages from ros-kinetic-desktop-full
- roscpp
- nodelet
- std_msgs
- sensor_msgs
- geometry_msgs
- dynamic_reconfigure
- pcl_conversions
- cv_bridge
- libpcl-all
- libpcl-all-dev
- ros-kinetic-opencv3
其他包 来自intel
-
ros_intel_movidius_ncs VPU运行mobileNetSSD
-
或者
-
opencl_caffe GPU运行yolo_v2
NOTE: 跟踪特征依赖 OpenCV (3.3 preferred, >= 3.2 minimum). ROS Kinetic package "ros-kinetic-opencv3" (where OpenCV **3.3.1** is integrated). However, if you're using an old version of ROS Kinetic (where OpenCV **3.2** is integrated), 其他来源 [opencv_contrib](https://github.com/opencv/opencv_contrib). 需要编译 opencv_contrib (self-built) 和 opencv (ROS Kinetic provided) 查看 "/opt/ros/kinetic/share/opencv3/package.xml"
- to build 编译
cd ${ros_ws} # "ros_ws" is the catkin workspace root directory where this project is placed in
catkin_make
- to test 测试
catkin_make run_tests
- to install 安装
catkin_make install
传感器驱动 RGB-D camera
- librealsense2 tag v2.9.1 and realsense_ros_camera tag 2.0.2 if run with Intel RealSense D400
roslaunch realsense_ros_camera rs_rgbd.launch
- openni_launch or freenect_launch and their dependencies if run with Microsoft XBOX 360 Kinect
roslaunch openni_launch openni.launch
- ros_astra_camera if run with Astra Camera
roslaunch astra_launch astra.launch
-
launch with OpenCL caffe as detection backend yolo_v2 目标检测后端
roslaunch object_analytics_launch analytics_opencl_caffe.launch
这里会直接运行 opencl_caffe_launch)/launch/includes/nodelet.launch
-
launch with Movidius NCS as detection backend mobileNetSSD 目标检测后端
roslaunch object_analytics_launch analytics_movidius_ncs.launch
这里会直接运行 movidius_ncs_launch)/launch/includes/ncs_stream_detection.launch
Frequently used options
-
input_points Specify arg "input_points" for the name of the topic publishing the sensor_msgs::PointCloud2 messages by RGB-D camera. Default is "/camera/depth_registered/points" (topic compliant with ROS OpenNI launch)
-
aging_th 跟踪队列长度 Specifiy tracking aging threshold, number of frames since last detection to deactivate the tracking. Default is 16.
-
probability_th 跟踪置信度 Specify the probability threshold for tracking object. Default is "0.5".
roslaunch object_analytics_launch analytics_movidius_ncs.launch aging_th:=30 probability_th:="0.3"
-
RGB图像 object_analytics/rgb (sensor_msgs::Image)
点云 object_analytics/pointcloud (sensor_msgs::PointCloud2)
定位信息(3d边框) object_analytics/localization (object_analytics_msgs::ObjectsInBoxes3D)
跟踪信息 object_analytics/tracking (object_analytics_msgs::TrackedObjects)
检测信息(2d边框)object_analytics/detection (object_msgs::ObjectsInBoxes)
1. RGBD传感器预处理分割器 splitter
输入: /camera/depth_registered/points
输出: pointcloud 3d点
输出: rgb 2d图像
object_analytics_nodelet/splitter/SplitterNodelet
2. 点云分割处理器 segmenter
object_analytics_launch/launch/includes/segmenter.launch
输入: pointcloud 3d点
输出: segmentation 分割
object_analytics_nodelet/segmenter/SegmenterNodelet
object_analytics_nodelet/src/segmenter/segmenter_nodelet.cpp
订阅发布话题后
std::unique_ptr<Segmenter> impl_;
点云话题回调函数:
boost::shared_ptr<ObjectsInBoxes3D> msg = boost::make_shared<ObjectsInBoxes3D>();// 3d框
msg->header = points->header;
impl_->segment(points, msg);//检测
pub_.publish(msg); //发布检测消息
object_analytics_nodelet/src/segmenter/segmenter.cpp
a. 首先 ros点云消息转化成 pcl点云消息
const sensor_msgs::PointCloud2::ConstPtr& points;
PointCloudT::Ptr pointcloud(new PointCloudT);
fromROSMsg<PointT>(*points, pcl_cloud);
b. 执行分割 Segmenter::doSegment()
std::vector<PointIndices> cluster_indices;// 点云所属下标
PointCloudT::Ptr cloud_segment(new PointCloudT);// 分割点云
std::unique_ptr<AlgorithmProvider> provider_;
std::shared_ptr<Algorithm> seg = provider_->get();// 分割算法
seg->segment(cloud, cloud_segment, cluster_indices);// 执行分割
AlgorithmProvider -> virtual std::shared_ptr<Algorithm> get() = 0;
Algorithm::segment()
object_analytics_nodelet/src/segmenter/organized_multi_plane_segmenter.cpp
class OrganizedMultiPlaneSegmenter : public Algorithm
OrganizedMultiPlaneSegmenter 类集成 Algorithm类
分割算法 segment(){} 基于pcl算法
1. 提取点云法线 OrganizedMultiPlaneSegmenter::estimateNormal()
2. 分割平面 OrganizedMultiPlaneSegmenter::segmentPlanes() 平面系数模型分割平面
3. 去除平面后 分割物体 OrganizedMultiPlaneSegmenter::segmentObjects() 欧氏距离聚类分割
c. 生成消息 Segmenter::composeResult()
for (auto& obj : objects)
{
object_analytics_msgs::ObjectInBox3D oib3;
oib3.min = obj.getMin();
oib3.max = obj.getMax();
oib3.roi = obj.getRoi();
msg->objects_in_boxes.push_back(oib3);
}
3. 3d定位器 merger
输入: 2d检测分割结果 detection
输入: 3d检测分割结果 segmentation
输出: 3d定位结果 localization
object_analytics_nodelet/merger/MergerNodelet
4. 目标跟踪器 tracker
输入: 2d图像 rgb input_rgb
输入: 2d检测分割结果 detection input_2d
输出: 跟踪结果 tracking output
参数: 跟踪帧队列长度: aging_th:default="30";
参数: 跟踪置信度: probability_th" default="0.5"
object_analytics_nodelet/tracker/TrackingNodelet
5. 3d定位可视化 visualization3d localization
输入: 2d检测结果 "detection_topic" default="/object_analytics/detection"
输入: 3d检测结果 "localization_topic" default="/object_analytics/localization"
输入: 2d跟踪结果 "tracking_topic" default="/object_analytics/tracking"
输出: rviz可视化话题 "output_topic" default="localization_rviz"
6. 2d跟踪可视化 visualization2d
输入: 2d检测结果 "detection_topic" default="/object_analytics/detection"
输入: 2d跟踪结果 "tracking_topic" default="/object_analytics/tracking"
输入: 2d图像 "image_topic" default="/object_analytics/rgb"
输出: rviz可视化话题 ""output_topic" default="tracking_rviz"
opencl_caffe_launch/launch/includes/nodelet.launch
输入: 2d图像 /usb_cam/image_raw input_topic
输出: 2d检测分割结果 input_detection output_topic
参数文件: param_file default= find opencl_caffe_launch/launch/includes/default.yaml"
模型文件 net_config_path: "/opt/clCaffe/models/yolo/yolo416/yolo_fused_deploy.prototxt"
权重文件 weights_path: "/opt/clCaffe/models/yolo/yolo416/fused_yolo.caffemodel"
类别标签文件 labels_path: "/opt/clCaffe/data/yolo/voc.txt"
节点: opencl_caffe/opencl_caffe_nodelet
opencl_caffe/src/nodelet.cpp
Nodelet::onInit() ---> loadResources()
检测器 detector_.reset(new DetectorGpu());
载入配置文件 detector_->loadResources(net_config_path, weights_path, labels_path)
订阅话题回调函数 sub_ = getNodeHandle().subscribe("/usb_cam/image_raw", 1, &Nodelet::cbImage, this);
Nodelet::cbImage();
网络前向推理 detector_->runInference(image_msg, objects)
发布话题 pub_.publish(objects);
DetectorGpu 类
opencl_caffe/src/detector_gpu.cpp
网络初始化:
net.reset(new caffe::Net<Dtype>(net_cfg, caffe::TEST, caffe::Caffe::GetDefaultDevice()));
net->CopyTrainedLayersFrom(weights);
模式:
caffe::Caffe::set_mode(caffe::Caffe::GPU);
caffe::Caffe::SetDevice(0);
载入图像:
cv::cvtColor(cv_bridge::toCvShare(image_msg, "rgb8")->image, image, cv::COLOR_RGB2BGR);
initInputBlob(resizeImage(image), input_channels);
网络前传:
net->Forward();
获取网络结果:
caffe::Blob<Dtype>* result_blob = net->output_blobs()[0];
const Dtype* result = result_blob->cpu_data();
const int num_det = result_blob->height();
检测结果:
object_msgs::ObjectInBox object_in_box;
object_in_box.object.object_name = labels_list[classid];
object_in_box.object.probability = confidence;
object_in_box.roi.x_offset = left;
object_in_box.roi.y_offset = top;
object_in_box.roi.height = bot - top;
object_in_box.roi.width = right - left;
objects.objects_vector.push_back(object_in_box);
movidius_ncs_launch/launch/includes/ncs_stream_detection.launch
输入: 2d图像 input_rgb input_topic
输出: 2d检测分割结果 input_detection output_topic
参数:
模型类型 name="cnn_type" default="mobilenetssd"
模型配置文件 name="param_file" default="$(find movidius_ncs_launch)/config/mobilenetssd.yaml"
网络图配置文件 graph_file_path: "/opt/movidius/ncappzoo/caffe/SSD_MobileNet/graph"
类别文件voc21 category_file_path: "/opt/movidius/ncappzoo/data/ilsvrc12/voc21.txt"
网络输入尺寸 network_dimension: 300
通道均值 :
channel1_mean: 127.5
channel2_mean: 127.5
channel3_mean: 127.5
归一化:
scale: 0.007843
节点文件 movidius_ncs_stream/NCSNodelet movidius_ncs_stream/src/ncs_nodelet.cpp
输入话题 input_topic : 2d图像 /camera/rgb/image_raw
输出话题 output_topic : 2d检测框结果 detected_objects
ncs_manager_handle_ = std::make_shared<movidius_ncs_lib::NCSManager>();
movidius_ncs_lib::NCSManager 来自 movidius_ncs_lib/src/ncs_manager.cpp
NCSImpl::init(){ }
订阅 rgb图像的回调函数 cbDetect()
sub_ = it->subscribe("/camera/rgb/image_raw", 1, &NCSImpl::cbDetect, this);
cbDetect(){ }
1. 从话题复制图像
cv::Mat camera_data = cv_bridge::toCvCopy(image_msg, "bgr8")->image;
2. 提取检测结果回调函数
FUNP_D detection_result_callback = boost::bind(&NCSImpl::cbGetDetectionResult, this, _1, _2);
3. 进行目标检测
ncs_manager_handle_->detectStream(camera_data, detection_result_callback, image_msg);
NCSManager::detectStream(){}
得到检测结果 : movidius_ncs_lib::DetectionResultPtr result;
检测结果:
for (auto item : result->items_in_boxes)
object_msgs::ObjectInBox obj;
obj.object.object_name = item.item.category;
obj.object.probability = item.item.probability;
obj.roi.x_offset = item.bbox.x;
obj.roi.y_offset = item.bbox.y;
obj.roi.width = item.bbox.width;
obj.roi.height = item.bbox.height;
objs_in_boxes.objects_vector.push_back(obj);
发布检测结果:
objs_in_boxes.header = header;
objs_in_boxes.inference_time_ms = result->time_taken;
pub_.publish(objs_in_boxes);
topic | fps | latency sec | |
OpenCL Caffe | |||
localization | 6.63 | 0.23 | |
detection | 8.88 | 0.17 | |
tracking | 12.15 | 0.33 | |
Movidius NCS | |||
localization | 7.44 | 0.21 | |
detection | 10.5 | 0.15 | |
tracking | 13.85 | 0.24 |
- CNN model of Movidius NCS is MobileNet
- Hardware: Intel(R) Xeon(R) CPU E3-1275 v5 @3.60GHz, 32GB RAM, Intel(R) RealSense R45
Steps to enable visualization on RViz are as following
roslaunch object_analytics_visualization rviz.launch