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

      项目链接: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文件并根据需求进行修改:

GPU=1 #如果使用GPU设置为1,CPU设置为0
CUDNN=0  #如果使用CUDNN设置为1,否则为0
OPENCV=1 #如果调用摄像头,还需要设置OPENCV为1,否则为0
OPENMP=0  #如果使用OPENMP设置为1,否则为0
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文件:

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

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

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

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

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

[net]
# Testing                 ### 测试模式  
# batch=1
# subdivisions=1
# Training                ### 训练模式,每次前向的图片数目 = batch/subdivisions
batch=64
subdivisions=16
width=416               ### 网络的输入宽、高、通道数    
height=416
channels=3
momentum=0.9          ### 动量
decay=0.0005            ### 权重衰减
angle=0
saturation = 1.5          ### 饱和度 
exposure = 1.5           ### 曝光度
hue=.1                  ### 色调
learning_rate=0.001       ### 学习率
burn_in=1000            ### 学习率控制的参数
max_batches = 10000     ### 迭代次数
policy=steps             ### 学习率策略
steps=40000,45000       ### 学习率变动步长
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。(是否要多尺度输出。)

        如下:

[convolutional]
size=1
stride=1
pad=1
filters=18             #############
activation=linear

[yolo]
mask = 6,7,8
anchors = 10,13,  16,30,  33,23,  30,61,  62,45,  59,119,  116,90,  156,198,  373,326
classes=1             ###############
num=9
jitter=.3
ignore_thresh = .5
truth_thresh = 1
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文件中的测试模式打开。

[net]
# Testing
 batch=1
 subdivisions=1
# Training
#batch=64
#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摄像头使用的那篇文章,有:

camera_reading:
  topic: /usb_cam/image_raw
  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,如下:

yolo_model:

  config_file:
    name: cabin_yolov3.cfg
  weight_file:
    name: cabin_yolov3.weights
  threshold:
    value: 0.3
  detection_classes:
    names:
      - 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路径。如下:

<?xml version="1.0" encoding="utf-8"?>

<launch>
  <!-- Console launch prefix -->
  <arg name="launch_prefix" default=""/>
  <arg name="image" default="/usb_cam/image_raw" />

  <!-- Config and weights folder. -->
  <arg name="yolo_weights_path"          default="$(find darknet_ros)/yolo_network_config/weights"/>
  <arg name="yolo_config_path"           default="$(find darknet_ros)/yolo_network_config/cfg"/>

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

  <!-- Load parameters -->
  <rosparam command="load" ns="darknet_ros" file="$(arg ros_param_file)"/>
  <rosparam command="load" ns="darknet_ros" file="$(arg network_param_file)"/>

  <!-- Start darknet and ros wrapper -->
  <node pkg="darknet_ros" type="darknet_ros" name="darknet_ros" output="screen" launch-prefix="$(arg launch_prefix)">
    <param name="weights_path"          value="$(arg yolo_weights_path)" />
    <param name="config_path"           value="$(arg yolo_config_path)" />
    <remap from="camera/rgb/image_raw"  to="$(arg image)" />
  </node>

 <!--<node name="republish" type="republish" pkg="image_transport" output="screen" 	args="compressed in:=/front_camera/image_raw raw out:=/camera/image_raw" /> -->
</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这个文件。

        显然:

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

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

        我们打开ros.yaml:

subscribers:

  camera_reading:
    topic: /usb_cam/image_raw
    queue_size: 1

actions:

  camera_reading:
    name: /darknet_ros/check_for_objects

publishers:

  object_detector:
    topic: /darknet_ros/found_object
    queue_size: 1
    latch: false

  bounding_boxes:
    topic: /darknet_ros/bounding_boxes
    queue_size: 1
    latch: false

  detection_image:
    topic: /darknet_ros/detection_image
    queue_size: 1
    latch: true

image_view:

  enable_opencv: true
  wait_key_delay: 1
  enable_console_output: true

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

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

  config_file:
    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中:

  weight_file:
    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"/>

  • 5
    点赞
  • 42
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值