项目来源于:小车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,如有侵权,请联系删除。

Logo

DAMO开发者矩阵,由阿里巴巴达摩院和中国互联网协会联合发起,致力于探讨最前沿的技术趋势与应用成果,搭建高质量的交流与分享平台,推动技术创新与产业应用链接,围绕“人工智能与新型计算”构建开放共享的开发者生态。

更多推荐