机器人操作系统ROS(15) ROS目标检测
项目来源于:小车yolo机械臂(一)ros下gazebo搭建小车(可键盘控制)安装摄像头仿真 加载yolo检测识别标记物体
下载项目地址参照上述博客:github项目
有两个包,第一个是darknet_ros(用于yolo的目标检测);
第二个是mrobot_gazebo(在ros下小车的仿真)。
因为yolo系列需要权重文件才能检测,原作者在github上为了压缩空间没有下载,在编译时会自动检测,没有的话会自动下载–耗时,因此最好自己先下载权重文件,再去编译。
权重文件路径如下图:txt文档提供了下载链接,下载到这个文件夹下即可。

1.本地环境搭建
# 创建新的工作空间
cd ~
mkdir detect_ws
cd detect_ws
mkdir src
cd src
catkin_init_workspace
# 这里将GitHub上的两个文件放到src目录下
cd ..
catkin_make install
# 或者
catkin_make -DCMAKE_BUILD_TYPE=Release
# 正常编译是没问题
# 编译成功!
2.加入环境变量
sudo gedit ~/.bashrc
# 在最下面加入以下:
source /home/ros/detect_ws/devel/setup.bash
# 保存! 退出
# 生效命令:
source ~/.bashrc
使用本地摄像头测试
darknet_ros会直接订阅指定的图像话题名,然后对图像进行检测,绘制检测框,并发布相应的检测话题。
1.启动摄像头
下载ROS官方的usb_cam驱动包,可以直接将电脑自带摄像头或连接电脑的USB摄像头采集的图像发布为ROS图像话题。
下载摄像头驱动:sudo apt-get install ros-kinectic-usb-cam
发布摄像头图像话题:roslaunch usb_cam usb_cam-test.launch
如果launch出现如下错误:

下载image_view:sudo apt-get install ros-kinetic-image-view
再次运动launch即可,现在应该是可以打开摄像头的

启动检测darknet_ros
不要把前面的摄像头关闭
先将camera_reading下topic里面的camera改为刚刚下载使用的usb_cam,这样改完topic,yolo就可以拿到前置摄像头的图像。

修改为:

保存后,再去启动检测的launch
运行darknet_ros
roslaunch darknet_ros darknet_ros.launch

这个错误可以查看解决
运行结果如下:


上面这个launch是yoyo-v2检测结果,好像只支持检测15个类别物体(不太了解),但是检测速度很快,
如果想要检测人可以运行下面命令,但是亲测好像很卡顿。
roslaunch darknet_ros yolo_v3.launch


gazebo仿真检测
原作者写得很详细,只要上述的本地摄像头没有问题,后面应该都正常,具体步骤请参照小车yolo机械臂(一)ros下gazebo搭建小车(可键盘控制)安装摄像头仿真 加载yolo检测识别标记物体
使用GPU加速
原文:darknet_ros加速–使用GPU和CUDA 还没有测试
第一处:更改Makefile前两行GPU和CUDNN的配置:
把0改成1 这里需要说明一下:ros-kinetic版本自带的opencv是3.3.1版本的,而darknet网络模型使用的yolov3要求版本在3.4.2以上,也就是说需要安装别的版本的opencv,但是实际用的是哪个版本的opencv我暂时还没有弄清楚

第二处:更改CUDA的路径:

在这里改成自己对应的本地路径
第三处:23行,修改NVCC的路径

第四处:更改第7行的ARCH,改成自己显卡的算力,这里我在官网上查询的算力为6.1,另外算力表也可以百度查查看,没有新的显卡用,我没怎么关注了。。。唉

修改完成后编译:在darknet_ros/darknet文件夹下编译输入make
~/ros1_ws/src/darknet_ros/darknet$ make
当然你会报错的,就像我一样,但是不要紧,有解决的办法:如何解决pjreddie版darknet不能使用cudnn8编译的问题 
大致原因就是,只支持到cudnn7.x,也就是说我们需要把8的内容添加一些,对于本小白还是有点担心的,只能上了。
打开报错文件的路径:/home/groot/ros1_ws/src/darknet_ros/darknet/src/convolutional_layer.c
添加这两行命令:
#include <stdio.h>
#include <time.h>
//下面是添加的命令
#define PRINT_CUDNN_ALGO 0
#define MEMORY_LIMIT 2000000000
#ifdef AI2
#include "xnor_layer.h"
#endif
然后大段的代码复制粘贴在这个位置:
#ifdef GPU
#ifdef CUDNN
void cudnn_convolutional_setup(layer *l)
{
...
#if CUDNN_MAJOR >= 7
cudnnSetConvolutionGroupCount(l->convDesc, l->groups);
#else
if(l->groups > 1){
error("CUDNN < 7 doesn't support groups, please upgrade!");
}
#endif
//注意下面是需要添加的代码,一直到底
#if CUDNN_MAJOR >= 8
int returnedAlgoCount;
cudnnConvolutionFwdAlgoPerf_t fw_results[2 * CUDNN_CONVOLUTION_FWD_ALGO_COUNT];
cudnnConvolutionBwdDataAlgoPerf_t bd_results[2 * CUDNN_CONVOLUTION_BWD_DATA_ALGO_COUNT];
cudnnConvolutionBwdFilterAlgoPerf_t bf_results[2 * CUDNN_CONVOLUTION_BWD_FILTER_ALGO_COUNT];
cudnnFindConvolutionForwardAlgorithm(cudnn_handle(),
l->srcTensorDesc,
l->weightDesc,
l->convDesc,
l->dstTensorDesc,
CUDNN_CONVOLUTION_FWD_ALGO_COUNT,
&returnedAlgoCount,
fw_results);
for(int algoIndex = 0; algoIndex < returnedAlgoCount; ++algoIndex){
#if PRINT_CUDNN_ALGO > 0
printf("^^^^ %s for Algo %d: %f time requiring %llu memory\n",
cudnnGetErrorString(fw_results[algoIndex].status),
fw_results[algoIndex].algo, fw_results[algoIndex].time,
(unsigned long long)fw_results[algoIndex].memory);
#endif
if( fw_results[algoIndex].memory < MEMORY_LIMIT ){
l->fw_algo = fw_results[algoIndex].algo;
break;
}
}
cudnnFindConvolutionBackwardDataAlgorithm(cudnn_handle(),
l->weightDesc,
l->ddstTensorDesc,
l->convDesc,
l->dsrcTensorDesc,
CUDNN_CONVOLUTION_BWD_DATA_ALGO_COUNT,
&returnedAlgoCount,
bd_results);
for(int algoIndex = 0; algoIndex < returnedAlgoCount; ++algoIndex){
#if PRINT_CUDNN_ALGO > 0
printf("^^^^ %s for Algo %d: %f time requiring %llu memory\n",
cudnnGetErrorString(bd_results[algoIndex].status),
bd_results[algoIndex].algo, bd_results[algoIndex].time,
(unsigned long long)bd_results[algoIndex].memory);
#endif
if( bd_results[algoIndex].memory < MEMORY_LIMIT ){
l->bd_algo = bd_results[algoIndex].algo;
break;
}
}
cudnnFindConvolutionBackwardFilterAlgorithm(cudnn_handle(),
l->srcTensorDesc,
l->ddstTensorDesc,
l->convDesc,
l->dweightDesc,
CUDNN_CONVOLUTION_BWD_FILTER_ALGO_COUNT,
&returnedAlgoCount,
bf_results);
for(int algoIndex = 0; algoIndex < returnedAlgoCount; ++algoIndex){
#if PRINT_CUDNN_ALGO > 0
printf("^^^^ %s for Algo %d: %f time requiring %llu memory\n",
cudnnGetErrorString(bf_results[algoIndex].status),
bf_results[algoIndex].algo, bf_results[algoIndex].time,
(unsigned long long)bf_results[algoIndex].memory);
#endif
if( bf_results[algoIndex].memory < MEMORY_LIMIT ){
l->bf_algo = bf_results[algoIndex].algo;
break;
}
}
#else
cudnnGetConvolutionForwardAlgorithm(cudnn_handle(),
l->srcTensorDesc,
l->weightDesc,
l->convDesc,
l->dstTensorDesc,
CUDNN_CONVOLUTION_FWD_SPECIFY_WORKSPACE_LIMIT,
2000000000,
&l->fw_algo);
cudnnGetConvolutionBackwardDataAlgorithm(cudnn_handle(),
l->weightDesc,
l->ddstTensorDesc,
l->convDesc,
l->dsrcTensorDesc,
CUDNN_CONVOLUTION_BWD_DATA_SPECIFY_WORKSPACE_LIMIT,
2000000000,
&l->bd_algo);
cudnnGetConvolutionBackwardFilterAlgorithm(cudnn_handle(),
l->srcTensorDesc,
l->ddstTensorDesc,
l->convDesc,
l->dweightDesc,
CUDNN_CONVOLUTION_BWD_FILTER_SPECIFY_WORKSPACE_LIMIT,
2000000000,
&l->bf_algo);
#endif
后面结束的样子

然后再编译,这个问题就解决了。
在工作空间编译darknet_ros
catkin_make -DCMAKE_BUILD_TYPE=Release
此时会开始编译整个项目,编译完成后会检查{catkin_ws}/darknet_ros/darknet_ros/yolo_network_config/weights文件下有没有yolov2-tiny.weights和yolov3.weights两个模型文件,默认下载好的代码里面为了节省体积是不带这两个模型文件的。因此编译之后会自动开始下载模型文件,此时又是一段漫长的等待时间。
如果刚好你之前已经下载好了模型文件,那就好了,在开始编译之前就把模型文件拷贝到上述文件夹下,就不会再次下载了。
让我们开始检测吧~
相比之前的1帧,现在FPS已经达到了18.8,我基本满意了。

本文转自 https://blog.csdn.net/weixin_42458522/article/details/120205982,如有侵权,请联系删除。
DAMO开发者矩阵,由阿里巴巴达摩院和中国互联网协会联合发起,致力于探讨最前沿的技术趋势与应用成果,搭建高质量的交流与分享平台,推动技术创新与产业应用链接,围绕“人工智能与新型计算”构建开放共享的开发者生态。
更多推荐


所有评论(0)