当前位置:   article > 正文

基于ROS搭建简易软件框架实现ROV水下目标跟踪(十三)--基于darknet_ros目标识别模型的训练和部署_darknet_ros opencv=1

darknet_ros opencv=1

      项目链接:https://github.com/cabinx/cabin_auv_ws

      在目标跟踪时,摄像头提供实时的图片信息,我们需要识别出图片目标,且输出目标在图片中的位置,为后续的控制提供条件。在demo中,我是借助darknet_ros实现这一目标。当然这一模块可以替换成性能更优秀的识别算法。

      darknet_ros为yolov3在ros下的一个工具包(https://github.com/leggedrobotics/darknet_ros)。需要对yolov3的使用有所了解(YOLO: Real-Time Object Detection)。例程我就不介绍了,可以在网上搜索。在此主要基于demo测试介绍我个人的使用情况,主要包括摄像头驱动、数据集制作、模型训练、模型部署。

      本文介绍使用darknet_ros进行目标识别模型的训练及部署。

一、训练模型

        这里我主要参考了博客:darknet-yolov3训练自己的数据集(超详细) - AnswerThe - 博客园,同时结合yolo官网教程。在此默认已配置好GPU及CUDA等环境。训练数据集亦已准备好。

1、编译darknet(启用GPU)

        在/darknet_ros/darknet路径下找到Makefile文件并根据需求进行修改:

  1. GPU=1 #如果使用GPU设置为1,CPU设置为0
  2. CUDNN=0 #如果使用CUDNN设置为1,否则为0
  3. OPENCV=1 #如果调用摄像头,还需要设置OPENCV为1,否则为0
  4. OPENMP=0 #如果使用OPENMP设置为1,否则为0
  5. DEBUG=0 #如果使用DEBUG设置为1,否则为0

        关于ARCH值的设置,可以到NVIDIA官网查询自身显卡的算力(CUDA GPUs | NVIDIA Developer):

        如2080TI,则为:

ARCH = -gencode arch=compute_75, code=[sm_75,compute_75]

        编译:

make

       编译完成后可以选择进行验证,下载训练好的模型:

wget https://pjreddie.com/media/files/yolov3.weights

        运行detector:

./darknet detect cfg/yolov3.cfg yolov3.weights data/dog.jpg

        若能识别图片中的物体,则证明darknet安装配置成功。

        顺便下载预训练模型权值后边备用。

wget https://pjreddie.com/media/files/darknet53.conv.74

2、配置文件

        进入路径darknet/cfg,复制yolov3-voc.cfg、voc.data,并更名为cabin_yolov3.cfg,cabin_data.data。

        ①新建cabin_name.names文件,每一行填入一类目标。如我的demo只有一类目标,所以cabin_name.names文件为:

sea_cucumber

        ②再来看cabin_data.data文件:

  1. classes= 1
  2. train = /home/pcl-02/darknet_ws/src/darknet_ros/darknet/cabin_data/data/ImageSets/Main/train.txt
  3. valid = /home/pcl-02/darknet_ws/src/darknet_ros/darknet/cabin_data/data/ImageSets/Main/val.txt
  4. names = cfg/cabin_name.names
  5. backup = /home/pcl-02/darknet_ws/src/darknet_ros/darknet/cabin_data/data/weights

        train和valid分别为训练集和验证集路径,与上一篇数据集制作的博客相对应;

        names为新建的类别名称文件,上文已提及;

        buckup为训练出来的模型的存储路径。

       ③ 最后看cabin_yolov3.cfg文件,我们首先将训练模式打开:

  1. [net]
  2. # Testing ### 测试模式
  3. # batch=1
  4. # subdivisions=1
  5. # Training ### 训练模式,每次前向的图片数目 = batch/subdivisions
  6. batch=64
  7. subdivisions=16
  8. width=416 ### 网络的输入宽、高、通道数
  9. height=416
  10. channels=3
  11. momentum=0.9 ### 动量
  12. decay=0.0005 ### 权重衰减
  13. angle=0
  14. saturation = 1.5 ### 饱和度
  15. exposure = 1.5 ### 曝光度
  16. hue=.1 ### 色调
  17. learning_rate=0.001 ### 学习率
  18. burn_in=1000 ### 学习率控制的参数
  19. max_batches = 10000 ### 迭代次数
  20. policy=steps ### 学习率策略
  21. steps=40000,45000 ### 学习率变动步长
  22. scales=.1,.1

        其它诸如学习率learning_rate,迭代次数max_batches等等网上介绍很多,我就不重复了。

        然后搜索关键词yolo,一共有3处含yolo,每处需要修改2个地方。

        filters:3*(5+len(classes));

        其中:classes: 目标种类,这里以我的工程为例

        filters = 18

        classes = 1

        可修改:random = 1:原来是1,显存小改为0。(是否要多尺度输出。)

        如下:

  1. [convolutional]
  2. size=1
  3. stride=1
  4. pad=1
  5. filters=18 #############
  6. activation=linear
  7. [yolo]
  8. mask = 6,7,8
  9. anchors = 10,13, 16,30, 33,23, 30,61, 62,45, 59,119, 116,90, 156,198, 373,326
  10. classes=1 ###############
  11. num=9
  12. jitter=.3
  13. ignore_thresh = .5
  14. truth_thresh = 1
  15. random=1 ###############

3、开始训练

./darknet detector train cfg/cabin_data.data cfg/cabin_yolov3.cfg darknet53.conv.74 -gpus 0,1

        在此,利用到了上文提及的下载好的预训练模型权值darknet53.conv.74。由于我训练时使用了两张显卡,故-gpus 0,1 。

        训练时得到的模型将位于cabin_name.names中backup一项设置的路径中。按上文中的配置,模型名为cabin_yolov3.backup。训练过程中实时的权值存储于该模型文件中,当判断已经收敛时,可以终止训练,下一步使用该模型时需要将其拷贝出来并修改其文件名为cabin_yolov3.weights。

        若模型因为训练不充分导致训练的效果不佳,可以在不修改参数的前提下基于该模型文件继续训练:

./darknet detector train cfg/cabin_data.data cfg/cabin_yolov3.cfg /home/pcl-02/darknet_ws/src/darknet_ros/darknet/cabin_data/data/weights/cabin_yolov3.backup -gpus 0,1

       关于如何判断训练已经收敛了,这里推荐一篇关于yolov3训练时输出log的文章解析:理解 YOLOv3 的训练输出日志信息_Right here, Code is Magic-CSDN博客_yolov3的输出是什么

        如下图所示:

    

        在此关注如下几项:

        256: 指示当前训练的迭代次数;

        3.784128: 是总体的 Loss(损失);

        4.452100 avg: 是平均 Loss, 这个数值应该越低越好, 一般来说, 一旦这个数值趋于稳定不下降时,就可以终止训练了;

        0.000009 rate: 代表当前的学习率, 是在.cfg文件中定义的;

        4.415291 seconds: 表示当前批次训练花费的总时间;

        32768 images:表示到目前为止, 参与训练的图片的总量。

4、测试模型

        在调试过程中,我直接用的录制的视频包进行验证,我会在下一部分的部署模型里介绍。但比较简单直接的方法可以用上文编译介绍部分中图片验证的方法。

        需要将cabin_yolov3.cfg文件中的测试模式打开。

  1. [net]
  2. # Testing
  3. batch=1
  4. subdivisions=1
  5. # Training
  6. #batch=64
  7. #subdivisions=16

二、模型部署

        基于darknet_ros模型部署主要参照了文章:ROS下实现darknet_ros(YOLO V3)检测_pd很不专业的博客-CSDN博客_ros yolov3

        输入输出如下:

        监听topic:/usb_cam/image_raw,格式sensor_msgs::Image,摄像头图片数据流;

        发布topic:/darknet_ros/bounding_boxes,格式darknet_ros_msgs::BoundingBoxes,目标在图片中的位置框图坐标。

1、离线调试

        完成训练后获得模型cabin_yolov3.weights。上一篇博客里介绍的数据包6.bag未参与数据集制作,即未参与模型训练,可用于离线测试。

①darknet_ros/config/ros.yaml

        此处配置监听及发布的topic的名称,需要注意监听的摄像头的数据流的topic。根据之前关于ros下USB摄像头使用的那篇文章,有:

  1. camera_reading:
  2. topic: /usb_cam/image_raw
  3. queue_size: 1

②darknet_ros/config/cabin_data.yaml

        此处载入训练好的模型及yolov3的配置文件。此处我将训练介绍部分的darknet下的cabin_yolov3.weights拷贝至/darknet_ros/yolo_network_config/weights;将cabin_yolov3.cfg拷贝至/darknet_ros/yolo_network_config/cfg。然后在darknet_ros/config下新建cabin_data.yaml,如下:

  1. yolo_model:
  2. config_file:
  3. name: cabin_yolov3.cfg
  4. weight_file:
  5. name: cabin_yolov3.weights
  6. threshold:
  7. value: 0.3
  8. detection_classes:
  9. names:
  10. - sea_cucumeber

        其中threshold为置信度,大于0.3时识别为目标物。

③darknet_ros/launch/cabin_darknet_ros.launch

        拷贝darknet_ros.launch并重命名为cabin_darknet_ros.launch。修改摄像头数据的topic名称/usb_cam/image_raw以及上文提及的配置文件cabin_data.yaml路径。如下:

  1. <?xml version="1.0" encoding="utf-8"?>
  2. <launch>
  3. <!-- Console launch prefix -->
  4. <arg name="launch_prefix" default=""/>
  5. <arg name="image" default="/usb_cam/image_raw" />
  6. <!-- Config and weights folder. -->
  7. <arg name="yolo_weights_path" default="$(find darknet_ros)/yolo_network_config/weights"/>
  8. <arg name="yolo_config_path" default="$(find darknet_ros)/yolo_network_config/cfg"/>
  9. <!-- ROS and network parameter files -->
  10. <arg name="ros_param_file" default="$(find darknet_ros)/config/ros.yaml"/>
  11. <arg name="network_param_file" default="$(find darknet_ros)/config/cabin_data.yaml"/>
  12. <!-- Load parameters -->
  13. <rosparam command="load" ns="darknet_ros" file="$(arg ros_param_file)"/>
  14. <rosparam command="load" ns="darknet_ros" file="$(arg network_param_file)"/>
  15. <!-- Start darknet and ros wrapper -->
  16. <node pkg="darknet_ros" type="darknet_ros" name="darknet_ros" output="screen" launch-prefix="$(arg launch_prefix)">
  17. <param name="weights_path" value="$(arg yolo_weights_path)" />
  18. <param name="config_path" value="$(arg yolo_config_path)" />
  19. <remap from="camera/rgb/image_raw" to="$(arg image)" />
  20. </node>
  21. <!--<node name="republish" type="republish" pkg="image_transport" output="screen" args="compressed in:=/front_camera/image_raw raw out:=/camera/image_raw" /> -->
  22. </launch>

④运行

        分别在终端中启动darknet_ros及播放数据包:

roslaunch darknet_ros cabin_darknet_ros.launch
rosbag play 6.bag

        效果如下:

        从效果上看,帧率很低;但从输出的yolo的log上看,帧率有60帧(使用的是双2080TI)。

        这就关系到前文提及的视频传输的时延。录制数据包时视频由水下的树莓派经电力载波线上传至岸上PC录制,不做处理时时延及丢帧非常明显,显然会对后面的跟踪控制部分造成影响。

2、在线部署

        离线调试成功后,这一步就非常简单了,水下摄像头接在树莓派上,岸上pc通过ssh登录到树莓派启动摄像头,此时网络中图片数据发布于/usb_cam/image_raw。

        此时就与离线调试一样了,在岸上PC启动darknet_ros即可。

=========================================================================         

       在这里我还是补充一下darknet_ros的配置文件吧,虽然有点绕,但我先前认为各文件的条理还是很清晰的,文件内容也很简单,稍微注意点就好,所以就不细说。配置文件没做好会出现各种各样的错误。

        回到cabin_darknet_ros.launch这个文件。

        显然:

  1. <!-- ROS and network parameter files -->
  2. <arg name="ros_param_file" default="$(find darknet_ros)/config/ros.yaml"/>
  3. <arg name="network_param_file" default="$(find darknet_ros)/config/cabin_data.yaml"/>

        ros.yaml和cabin_data.yaml就是两个需要先配置好的文件。

        我们打开ros.yaml:

  1. subscribers:
  2. camera_reading:
  3. topic: /usb_cam/image_raw
  4. queue_size: 1
  5. actions:
  6. camera_reading:
  7. name: /darknet_ros/check_for_objects
  8. publishers:
  9. object_detector:
  10. topic: /darknet_ros/found_object
  11. queue_size: 1
  12. latch: false
  13. bounding_boxes:
  14. topic: /darknet_ros/bounding_boxes
  15. queue_size: 1
  16. latch: false
  17. detection_image:
  18. topic: /darknet_ros/detection_image
  19. queue_size: 1
  20. latch: true
  21. image_view:
  22. enable_opencv: true
  23. wait_key_delay: 1
  24. enable_console_output: true

        很简单,相机的topic,这个需要和系统里的topic相匹配,以及为输出的数据自定义topic名。

        我们再回到第二个文件cabin_data.yaml:

  1. config_file:
  2. name: cabin_yolov3.cfg

        这个是之前我们训练自己网络时的yolo的配置文件名,那这个文件路径在哪呢?在cabin_darknet_ros.launch里。也就是说该路径下要有cabin_yolov3.cfg的配置文件,当然这个路径是可以自由配置的。使用时别忘了将模式改成test。

 <arg name="yolo_config_path"           default="$(find darknet_ros)/yolo_network_config/cfg"/>

        同理,cabin_data.yaml中:

  1. weight_file:
  2. name: cabin_yolov3.weights

         这个是我们训练好的网络的权重文件名,注意,权重文件必须配合训练该文件的yolo的配置文件使用,对于cabin_yolov3.weights就是cabin_yolov3.cfg。

        那么,权重文件的存放路径同理在cabin_darknet_ros.launch中:

 <arg name="yolo_weights_path"          default="$(find darknet_ros)/yolo_network_config/weights"/>

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/AllinToyou/article/detail/390459
推荐阅读
相关标签
  

闽ICP备14008679号