简介:无人驾驶虚拟仿真环境中,道路障碍物默认有3种,路障、小鸭子(模拟行人)和小车,其中路障是静止状态,小鸭子和小车可以是静止状态,也可以是运动状态。障碍物色彩复杂多变、在道路中的位置随机且动态变化,普通的图像处理手段不再适用于障碍物的检测,在这里我们利用机器学习的手段来进行障碍物的检测。


目录

1、模型训练环境部署

2、制作训练数据集

3、模型训练

4、模型验证

5、模型导出

6、模型部署


1、模型训练环境部署

利用机器学习来进行障碍物检测,我们首先需要针对待识别物体建立一个模型,模型中包含待识别物体的特征数据,然后我们利用该模型对待识别图片进行推理判断,识别图中的物体并输出类型、位置等信息。

本文机器学习部分采用的是百度开源深度学习框架PaddlePaddle,下文先介绍paddle的安装过程,为了简化安装过程以及防止环境与其他软件冲突,我们通过环境管理工具conda来安装paddle。

1.1 安装conda

$ wget https://repo.anaconda.com/archive/Anaconda3-2020.11-Linux-x86_64.sh
$ bash Anaconda3-2020.11-Linux-x86_64.sh

首先,出现询问你是否同意anaconda3的license界面,输入yes,回车即可;

之后,会出现确认安装位置界面,直接enter默认即可;

最后,请求用户是否希望对Anaconda3进行初始化,输入no,回车即可:

注:这里也可以选择yes初始化conda,系统会自动配置环境变量,后续使用conda会比较方便,但是同时会改变python包安装位置,与前面的章节部分命令需要更改,对linux和python比较熟的可以直接初始化,不熟悉的可以先不初始化,每次开启终端都手动配置,后续需要直接初始化可以通过 conda init指令自行初始化。

安装完成后,重启终端,配置环境变量,

$ export ANACONDA3_HOME=/home/jab/anaconda3
$ export PATH=$PATH:$ANACONDA3_HOME/bin
$ conda -V

注:为方便使用可以编写环境配置脚本,每次打开终端执行脚本即可,脚本内容如下(anaconda_config.sh):

export ANACONDA3_HOME=/home/jab/anaconda3
export PATH=$ANACONDA3_HOME/bin:$PATH
source activate

保存到用户目录下,每次打开新终端执行:

$ source ~/anaconda_config.sh

1.2 为paddle安装单独创建环境

$ conda create -n paddle_env python=3.7

paddle_env 环境名称,自定义,后续进入环境时会使用

python=3.7 指定环境python版本,目前paddle适配最佳版本为3.7

创建完成后查看现有环境:

$ conda env list

其中base为我们原有环境,paddle_env是为新建环境,可通过conda activate命令进行切换。

1.3 安装paddle

激活paddle专用环境

$ conda activate paddle_env

配置conda软件源(这里用清华源)

$ conda config --add channels Index of /anaconda/pkgs/free/ | 清华大学开源软件镜像站 | Tsinghua Open Source Mirror
$ conda config --add channels Index of /anaconda/pkgs/main/ | 清华大学开源软件镜像站 | Tsinghua Open Source Mirror
$ conda config --set show_channel_urls yes

安装paddle2.2.1

$ conda install paddlepaddle==2.2.1 --channel Index of /anaconda/cloud/Paddle/ | 清华大学开源软件镜像站 | Tsinghua Open Source Mirror

测试,输入python或着python3,进入python命令行界面,依次输入import paddle, paddle.utils.run_check(),显示PaddlePaddle is installed successfully!等内容,说明paddle安装完成

$ python
>>> import paddle
>>> paddle.utils.run_check()

1.4 安装PaddleDetection

下载PaddleDetection

$ git clone https://gitee.com/paddlepaddle/PaddleDetection.git
$ cd PaddleDetection/

安装Cyphon

$ pip install Cython

安装软件需求的库

$ pip install -r requirements.txt

注:如果出现个别库下载特别缓慢还容易报错的情况,可以通过指定下载源的方式单独安装需要的版本,例如opencv_python、scipy等

$ pip install opencv_python==4.5.5.62 -i Simple Index
$ pip install scipy==1.7.3 -i Simple Index
​

安装软件

$ python setup.py install

测试

$ python ppdet/modeling/tests/test_architectures.py

显示 Ran 7 tests in 8.194s OK字样,说明PaddleDetection安装完成


2、制作训练数据集

数据集实质上就是一定数量的样本和标注,针对我们的数据集就是若干(最少几十张,多则不限)含有路障、小鸭子、小车的图片,以及图片中待识别对象的坐标信息,在虚拟仿真环境中生成数据集,我们需要以下几个步骤:

  1. 制作包含路障、小鸭子、小车的虚拟仿真环境
  2. 编程自动采集图片
  3. 筛选有效图片
  4. 数据集标注
  5. 转化格式

a. 制作地图

第一步,我们需要先制作包含待识别对象的虚拟仿真环境(objects_detect.yaml),在不同位置放置路障、小鸭子以及小车,小鸭子和小车可以设置为动态的:

tiles:
- [floor  , floor       , floor     , floor      , floor         , floor         , floor         , floor  ]
- [floor  , curve_left/W, straight/W, 3way_left/W, straight/W    , straight/W    , curve_left/N  , floor  ]
- [floor  , straight/S  , floor     , straight/N , floor         , floor         , straight/N    , floor  ]
- [floor  , 3way_left/S , straight/W, 4way       , straight/E    , straight/E    , 3way_left/N   , floor  ]
- [floor  , straight/S  , floor     , straight/S , floor         , floor         , straight/N    , floor  ]
- [floor  , curve_left/S, straight/E, 3way_left/E, straight/E    , straight/E    , curve_left/E  , floor  ]
- [floor  , floor       , floor     , floor      , floor         , floor         , floor         , floor  ]
# start_tile: [1, 1]
objects:duckie1:kind: duckiepos: [2.5,1.2]rotate: 0height: 0.06static: Falsecone1:kind: conepos: [4.5,1.7]rotate: 0height: 0.08duckie2:kind: duckiepos: [5.7,2.5]rotate: 0height: 0.06static: Falsecone2:kind: conepos: [5.2,4.5]rotate: 0height: 0.08duckie3:kind: duckiepos: [4.5,5.7]rotate: 0height: 0.06static: Falsecone3:kind: conepos: [2.5,5.2]rotate: 0height: 0.08duckie4:kind: duckiepos: [1.2,4.5]rotate: 0height: 0.06static: Falsecone4:kind: conepos: [1.7,2.5]rotate: 0height: 0.08duckie5:kind: duckiepos: [3.7,2.5]rotate: 0height: 0.06static: Falsecone5:kind: conepos: [2.5,3.2]rotate: 0height: 0.08duckie6:kind: duckiepos: [3.2,4.5]rotate: 0height: 0.06static: Falsecone6:kind: conepos: [4.5,3.7]rotate: 0height: 0.08duckiebot1:kind: duckiebotpos: [4.5, 5.75]rotate: 0height: 0.12static: Falseduckiebot2:kind: duckiebotpos: [6.5, 3.75]rotate: 0height: 0.12static: Falsetrafficlight1:kind: trafficlightplace:tile: [3,4]relative:~SE2Transform:p: [-0.18,-0.18]theta_deg: 135height: 0.3optional: truetrafficlight2:kind: trafficlightplace:tile: [6,4]relative:~SE2Transform:p: [-0.18,-0.18]theta_deg: 135height: 0.3optional: truetrafficlight3:kind: trafficlightplace:tile: [1,4]relative:~SE2Transform:p: [-0.18,-0.18]theta_deg: 135height: 0.3optional: truetrafficlight4:kind: trafficlightplace:tile: [3,6]relative:~SE2Transform:p: [-0.18,-0.18]theta_deg: 135height: 0.3optional: truetrafficlight5:kind: trafficlightplace:tile: [3,1]relative:~SE2Transform:p: [-0.18,-0.18]theta_deg: 135height: 0.3optional: true
tile_size: 0.585

仿真环境中我们放置了6只鸭子,6个路障以及2台小车:


因为需要大量数据,手动截图就不现实了,我们单独创建一个节点来进行图像截取。

b. 编程自动采集图片

进入ROS工作空间

$ cd ~/myros/catkin_ws/src

创建功能包

$ catkin_create_pkg image_collect rospy sensor_msgs

新建源码文件

$ touch image_collect/src/image_collect_node.py

新建启动脚本文件

$ mkdir -p image_collect/launch
$ touch image_collect/launch/start.launch

新建images文件夹,用来存储采集的图像

$ mkdir image_collect/images

修改编译配置文件

$ gedit image_collect/CMakeLists.txt

修改为

编辑启动脚本文件

$ gedit image_collect/launch/start.launch
<launch><arg name="veh"/><arg name="pkg_name" value="image_collect"/><arg name="node_name" value="image_collect_node"/><arg name="param_file_name" default="default" doc="Specify a param file. ex:megaman"/><arg name="required" default="false" /><group ns="$(arg veh)"><remap from="image_collect_node/image/compressed" to="duckiebot_node/image/compressed"/><node name="$(arg node_name)" pkg="$(arg pkg_name)" type="$(arg node_name).py" respawn="true" respawn_delay="10" output="screen" required="$(arg required)"></node></group>
</launch>

编辑源码

$ gedit image_collect/src/image_collect_node.py
#!/usr/lib/env python3import rospy
import cv2
import time
import os
from cv_bridge import CvBridgefrom sensor_msgs.msg import CompressedImageclass ImageCollectNode():def __init__(self):rospy.init_node("image_collect_node", anonymous=False)self.bridge = CvBridge()self.count = 0  #计数器,每30帧存一张图片self.filePath = os.path.abspath(__file__) #源码文件所在目录#用两次os.path.dirname()获取功能包目录self.imagesStorePath = os.path.dirname(os.path.dirname(self.filePath))#订阅图像话题rospy.Subscriber("~image/compressed", CompressedImage, self.cb_image)def cb_image(self, msg):if self.count==30:#图像格式转化为opencv格式image = self.bridge.compressed_imgmsg_to_cv2(msg)#取当前时间为图像文件名称fileName = time.time()#存储图片cv2.imwrite(self.imagesStorePath+"/images/"+str(fileName)+".jpg", image)self.count = 0else:self.count += 1               if __name__=='__main__':node = ImageCollectNode()rospy.spin()

返回ROS工作空间并进行编译、

$ cd ~/myros/catkin_ws
$ catkin_make

修改虚拟仿真环境地图map-name为objects_detect

$ gedit src/duckiebot/config/duckiebot_node/default.yaml
map-name: objects_detect

修改多节点启动脚本文件

$ gedit start.launch
<launch><arg name="veh" default="duckiebot"/><group><include file="$(find duckiebot)/launch/duckiebot.launch"><arg name="veh" value="$(arg veh)"/></include><include file="$(find anti_instagram)/launch/start.launch"><arg name="veh" value="$(arg veh)"/></include><include file="$(find line_detect)/launch/start.launch"><arg name="veh" value="$(arg veh)"/></include><include file="$(find lane_filter)/launch/start.launch"><arg name="veh" value="$(arg veh)"/></include><include file="$(find car_control)/launch/start.launch"><arg name="veh" value="$(arg veh)"/></include><include file="$(find image_collect)/launch/start.launch"><arg name="veh" value="$(arg veh)"/></include></group>
</launch>

配置环境变量,启动程序

$ source devel/setup.bash
$ roslaunch start.launch

在images文件夹内,就可以看到截取的图片:

数据集越大最终训练出来的模型识别准确度也会高一些,但是工作量和需要的时间也会增加,需要根据实际情况确定数据集的大小。


c. 筛选有效图片

截取的图片中有些图片是无效样本,照片中没有待识别对象,需要剔除,为防止数据集不够,在上一步中我们先采集400左右图片备用,可通过在文件夹内ctrl+A,全选照片后查看右下角统计数量,数量足够了就停止程序。

图片筛选可以纯手动筛选,但是容易比较慢,且容易误删,我们通过一段程序来完成图片筛选工作。

在同目录下新建used文件夹用来存放有效图片:

$ mkdir used

给所有图片统一重命名,方便后续处理。

在images文件夹内新建python脚本(image_filter.py):

$ touch ~/myros/catkin_ws/src/image_collect/images/image_filter.py
$ gedit ~/myros/catkin_ws/src/image_collect/images/image_filter.py
#!/usr/bin/env python3import os
import tkinter
from tkinter.messagebox import *
import cv2window = tkinter.Tk()
window.withdraw()
filenames=os.listdir(".")
for fn in filenames:if fn.endswith("jpg"):    image = cv2.imread(fn)cv2.imshow("image", image)cv2.waitKey(0)result = askquestion('筛选确认', '是否有效图片?')if result=='yes':cv2.imwrite("./used/"+fn, image)

运行python脚本:

$ python3 image_filter.py

按任意键弹窗询问是否有效图片,点yes复制图片到used目录下,点no显示下一张:

循环完所有图片,used目录下的就是有效图片:

注:尽量选取待识别物体图像比较明显一点的。

d. 数据集标注

图片筛选完成后,接下来需要进行标注,所谓标注,就是把每张图片中的待识别物体的位置用固定的格式记录下来,PaddleDetection支持VOC和COCO两种标注格式,我们这里使用Pascal VOC(Pascal Visual Object Classes)格式。另外,标注工具我们使用labelImg工具。

#安装labelImg

$ pip3 install labelImg

#打开软件

$ labelImg

#创建数据集文件目录

$ cd ~/PaddleDetection/dataset
$ mkdir duckieSet
$ cd duckieSet
$ mkdir Annotations
$ mkdir ImageSets
$ mkdir JPEGImages

JPEGImages中存放要训练的图片。

Annotations中这XML信息,XML文件名与训练图片的文件名一一对应。

ImageSets中存放文件夹Main,Main中存放四个txt文件,train存放着用于训练图片名字集合,test存放着用于测试的名字集合。

复制筛选出的图片至JPEGImages 目录下:

$ cp ~/myros/catkin_ws/src/image_collect/images/used/* ~/PaddleDetection/dataset/duckieSet/JPEGImages/
$ labelImg

Open Dir: 打开图片所在文件夹(JPEGImages)

Change Save Dir: 改变标注数据文件存放目录(Annotations)

数据格式默认PascalVOC

Create RectBox: 创建一个框用来定位物体,快捷按键 W

Next Image: 下一张图, 快捷按键 D

Prev Image: 上一张图片,快捷按键 A

Save:保存标注数据,快捷按键 CTRL+S

我们以下图为例,介绍具体标注过程:

点Create RectBox或者按W键,通过拖拉鼠标创建一个框,将待识别物体框选出来,弹窗中填入物体名称(duckie,duckiebot,cone)

点OK,继续框选下一个,直到图中所有待识别物体都被框选记录下来:

CTRL+S保存:

软件自动在设定目录下自动生成一个与图片名称相同的xml文件,完成一张图的标注,以此类推,完成所有样本图的标注。

$ cd ~/PaddleDetection/dataset/duckieSet

# 生成 label_list.txt 文件

$ echo -e "duckie\ncone\nduckiebot" > label_list.txt

# 生成 train.txt、valid.txt和test.txt列表文件

$ ls JPEGImages/*.jpg | shuf > all_image_list.txt
$ awk -F"/" '{print $2}' all_image_list.txt | awk -F".jpg" '{print $1}' | awk -F"\t" '{print "JPEGImages/"$1".jpg Annotations/"$1".xml"}' > all_list.txt

# 训练集、验证集、测试集比例分别约80%、10%、10%。

$ head -n 20 all_list.txt > test.txt
$ head -n 40 all_list.txt | tail -n 20 > valid.txt
$ tail -n 160 all_list.txt > train.txt

# 删除不用文件

$ rm -rf all_image_list.txt all_list.txt

3、模型训练

开始训练之前,我们需要先编写模型训练配置文件,具体流程如下:

$ cd ~/PaddleDetection/configs
$ mkdir -p duckie/_base_

新建配置文件yolov3_mobilenet_v1_duckietown.yml,主要说明依赖配置文件路径。

$ touch duckie/yolov3_mobilenet_v1_duckietown.yml
$ gedit duckie/yolov3_mobilenet_v1_duckietown.yml
_BASE_: ['../datasets/duckietown_voc.yml','../runtime.yml','_base_/optimizer_40e.yml','_base_/yolov3_mobilenet_v1.yml','_base_/yolov3_reader.yml',
]
pretrain_weights: https://paddledet.bj.bcebos.com/models/yolov3_mobilenet_v1_270e_coco.pdparams
weights: output/yolov3_mobilenet_v1_duckietown/model_finalYOLOv3Loss:ignore_thresh: 0.7label_smooth: true

新建配置文件duckietown_voc.yml,主要说明训练数据和验证数据的路径,包括数据格式(coco、voc等)

$ touch datasets/duckietown_voc.yml
$ gedit datasets/duckietown_voc.yml
metric: VOC
map_type: integral
num_classes: 3TrainDataset:!VOCDataSetdataset_dir: dataset/duckieSetanno_path: train.txtlabel_list: label_list.txtdata_fields: ['image', 'gt_bbox', 'gt_class', 'difficult']EvalDataset:!VOCDataSetdataset_dir: dataset/duckieSetanno_path: valid.txtlabel_list: label_list.txtdata_fields: ['image', 'gt_bbox', 'gt_class', 'difficult']TestDataset:!ImageFolderanno_path: dataset/duckieSet/label_list.txt

修改runtime.yml(在configs目录下),主要说明了公共的运行状态,比如说是否使用GPU、迭代轮数等等

$ gedit runtime.yml
use_gpu: false
log_iter: 20
save_dir: output
snapshot_epoch: 1
print_flops: false

新建配置文件optimizer_40e.yml,主要说明学习率和优化器配置

$ touch duckie/_base_/optimizer_40e.yml
$ gedit duckie/_base_/optimizer_40e.yml
epoch: 40LearningRate:base_lr: 0.0001schedulers:- !PiecewiseDecaygamma: 0.1milestones:- 32- 36- !LinearWarmupstart_factor: 0.3333333333333333steps: 100OptimizerBuilder:optimizer:momentum: 0.9type: Momentumregularizer:factor: 0.0005type: L2

新建配置文件yolov3_mobilenet_v1.yml,主要说明模型、和主干网络的情况

$ touch duckie/_base_/yolov3_mobilenet_v1.yml
$ gedit duckie/_base_/yolov3_mobilenet_v1.yml
architecture: YOLOv3
pretrain_weights: https://paddledet.bj.bcebos.com/models/pretrained/MobileNetV1_pretrained.pdparams
norm_type: sync_bnYOLOv3:backbone: MobileNetneck: YOLOv3FPNyolo_head: YOLOv3Headpost_process: BBoxPostProcessMobileNet:scale: 1feature_maps: [4, 6, 13]with_extra_blocks: falseextra_block_filters: []# use default config
# YOLOv3FPN:YOLOv3Head:anchors: [[10, 13], [16, 30], [33, 23],[30, 61], [62, 45], [59, 119],[116, 90], [156, 198], [373, 326]]anchor_masks: [[6, 7, 8], [3, 4, 5], [0, 1, 2]]loss: YOLOv3LossYOLOv3Loss:ignore_thresh: 0.7downsample: [32, 16, 8]label_smooth: falseBBoxPostProcess:decode:name: YOLOBoxconf_thresh: 0.005downsample_ratio: 32clip_bbox: truenms:name: MultiClassNMSkeep_top_k: 100score_threshold: 0.01nms_threshold: 0.45nms_top_k: 1000

新建配置文件yolov3_reader.yml,主要说明了读取后的预处理操作,比如resize、数据增强等等

$ touch duckie/_base_/yolov3_reader.yml
$ gedit duckie/_base_/yolov3_reader.yml
worker_num: 0
TrainReader:inputs_def:num_max_boxes: 50sample_transforms:- Decode: {}- Mixup: {alpha: 1.5, beta: 1.5}- RandomDistort: {}- RandomExpand: {fill_value: [123.675, 116.28, 103.53]}- RandomCrop: {}- RandomFlip: {}batch_transforms:- BatchRandomResize: {target_size: [320, 352, 384, 416, 448, 480, 512, 544, 576, 608], random_size: True, random_interp: True, keep_ratio: False}- NormalizeBox: {}- PadBox: {num_max_boxes: 50}- BboxXYXY2XYWH: {}- NormalizeImage: {mean: [0.485, 0.456, 0.406], std: [0.229, 0.224, 0.225], is_scale: True}- Permute: {}- Gt2YoloTarget: {anchor_masks: [[6, 7, 8], [3, 4, 5], [0, 1, 2]], anchors: [[10, 13], [16, 30], [33, 23], [30, 61], [62, 45], [59, 119], [116, 90], [156, 198], [373, 326]], downsample_ratios: [32, 16, 8]}batch_size: 8shuffle: truedrop_last: truemixup_epoch: 250use_shared_memory: trueEvalReader:inputs_def:num_max_boxes: 50sample_transforms:- Decode: {}- Resize: {target_size: [608, 608], keep_ratio: False, interp: 2}- NormalizeImage: {mean: [0.485, 0.456, 0.406], std: [0.229, 0.224, 0.225], is_scale: True}- Permute: {}batch_size: 1TestReader:inputs_def:image_shape: [3, 608, 608]sample_transforms:- Decode: {}- Resize: {target_size: [608, 608], keep_ratio: False, interp: 2}- NormalizeImage: {mean: [0.485, 0.456, 0.406], std: [0.229, 0.224, 0.225], is_scale: True}- Permute: {}batch_size: 1

配置文件完成后,开始训练,先进入paddle专用环境

$ cd ~
$ source anaconda_config.sh
$ conda activate paddle_env
$ cd PaddleDetection
$ python tools/train.py -c configs/duckie/yolov3_mobilenet_v1_duckietown.yml --eval --use_vdl=True --vdl_log_dir="./output"

等待训练完成。

我们截取部分训练数据,可见损失是收敛的。

4、模型验证

模型训练完成后,在output目录下生成训练结果

我们可以先通过命令行对模型进行验证

$ cd ~/PaddleDetection

单张图片验证,指定要验证的图片:

$ python tools/infer.py -c configs/duckie/yolov3_mobilenet_v1_duckietown.yml -o weights=output/yolov3_mobilenet_v1_duckietown/best_model.pdparams --infer_img=dataset/duckieSet/JPEGImages/16.jpg

多张图片验证,指定图片所在目录:

$ python tools/infer.py -c configs/duckie/yolov3_mobilenet_v1_duckietown.yml -o weights=output/yolov3_mobilenet_v1_duckietown/best_model.pdparams --infer_dir=dataset/duckieSet/JPEGImages

验证结果在outpu目录下:

由于我们数据集样本较少,而且训练参数没有针对性调优,识别结果不是特别好,对远处的物体识别好一点,近处反而识别效果较差,主要原因是我采集的样本中远景样本太多,导致模型忽略了近景物体的识别,而我们真实需要的是近景物体的识别,所以在地图制作和样本筛选的时候需要注意一下。

5、模型导出

$ cd ~/PaddleDetection

导出模型,默认存储路径 output_inference/yolov3_mobilenet_v1_duckietown:

$ python tools/export_model.py -c configs/duckie/yolov3_mobilenet_v1_duckietown.yml -o weights=output/yolov3_mobilenet_v1_duckietown/best_model.pdparams
$ ls output_inference/yolov3_mobilenet_v1_duckietown

验证导出的模型

$ python deploy/python/infer.py --model_dir=output_inference/yolov3_mobilenet_v1_duckietown --image_file=dataset/duckieSet/JPEGImages/16.jpg

可以看到检测出4个待测物体,并给出了置信度和坐标

6、模型部署

在模型实际部署时,我们需要拷贝两个文件夹的内容,一个是模型文件包,即output_inference/yolov3_mobilenet_v1_duckietown/,内含4个文件,另一个是python推理工具包,deploy/python/,内含推理所需要的一些工具。

为了测试部署效果,我们可以用在windows环境下通过conda新建一个测试环境,或者在其他linux电脑上创建环境,参考上文安装paddle,opencv以及yaml

注:yaml安装 conda install pyyaml

附推理源码:

import numpy as np
import cv2
import os
import yaml
from functools import reduce
from paddle.inference import Config
from paddle.inference import create_predictor
from preprocess import Resize, NormalizeImage, Permute
from visualize import visualize_box_mask#模型文件所在目录
model_dir='model_duckietown'
#待识别图片
image_file='JPEGImages/19.jpg'
#加载模型配置文件
deploy_file = os.path.join(model_dir, 'infer_cfg.yml')
with open(deploy_file) as f:yml_conf = yaml.safe_load(f)
#图片预处理配置
preprocess_infos = yml_conf['Preprocess']
#读取标签列表
labels = yml_conf['label_list']
#预测器配置
config = Config(os.path.join(model_dir, 'model.pdmodel'),os.path.join(model_dir, 'model.pdiparams'))
config.disable_gpu() #禁用GPU
config.set_cpu_math_library_num_threads(1) #设置线程数
config.disable_glog_info() #禁用识别过程日志输出
config.enable_memory_optim() #启用内存共享功能
config.switch_use_feed_fetch_ops(False) #禁用feed_fetch_ops功能
#加载预测器
predictor = create_predictor(config)
#初始化图片预处理操作
preprocess_ops = []
for op_info in preprocess_infos:new_op_info = op_info.copy()op_type = new_op_info.pop('type')preprocess_ops.append(eval(op_type)(**new_op_info))
#图片预处理
im_info = {'scale_factor': np.array([1., 1.], dtype=np.float32),'im_shape': None,}
with open(image_file, 'rb') as f:im_read = f.read()
data = np.frombuffer(im_read, dtype='uint8')
im = cv2.imdecode(data, 1)  # BGR mode, but need RGB mode
im = cv2.cvtColor(im, cv2.COLOR_BGR2RGB)
im_info['im_shape'] = np.array(im.shape[:2], dtype=np.float32)
im_info['scale_factor'] = np.array([1., 1.], dtype=np.float32)
for operator in preprocess_ops:im, im_info = operator(im, im_info)
#创建输入数据
inputs = {}
inputs['image'] = np.array((im, )).astype('float32')
inputs['im_shape'] = np.array((im_info['im_shape'], )).astype('float32')
inputs['scale_factor'] = np.array((im_info['scale_factor'], )).astype('float32')np_boxes, np_masks = None, None
# 获取输入的向量名称
input_names = predictor.get_input_names()
# 根据向量名称获取输入向量
# 拷贝数据到输入向量中
for i in range(len(input_names)):input_tensor = predictor.get_input_handle(input_names[i])input_tensor.copy_from_cpu(inputs[input_names[i]])
#使用预测器执行前向计算
predictor.run()# 获取输出的向量名称
output_names = predictor.get_output_names()
# 根据向量名称获取输出向量
# 将结果从输出向量中拷贝出来
boxes_tensor = predictor.get_output_handle(output_names[0])
#识别结果,二维数组,每一行第1个元素是结果类别编号,第2个是可信度,后4个是坐标,左上和右下两个点定位一个矩形
np_boxes = boxes_tensor.copy_to_cpu()
#检查数组结果是否符合正常结果
if reduce(lambda x, y: x * y, np_boxes.shape) < 6:print('[WARNNING] No object detected.')
else:results = {}results['boxes'] = np_boxes#用提供的工具在原有图像上画出检测物体i信息(位置框以及类别名称置可信度)im = visualize_box_mask(image_file, results, labels, 0.5)image = np.array(im)image = cv2.cvtColor(image, cv2.COLOR_RGB2BGR)cv2.imshow("result", image)cv2.waitKey(0)

执行结果

按照我们的类型列表,0代表duckie,1代表cone

无人驾驶虚拟仿真(十五)--障碍物检测与识别1相关推荐

  1. 无人驾驶虚拟仿真(五)--图像处理之色彩平衡

    简介:同样的物体在不同的光照环境中会出现色彩偏差,为了减少色彩偏差对系统检测造成的影响,在对图像进行识别前,需要先评估图像明暗度,计算出明暗阈值,通过对图像的色彩平衡处理,可以校正图像色偏,过饱和或饱 ...

  2. 无人驾驶虚拟仿真(十)--车辆姿态控制(PID)

    简介:在上一节内容中,我们估算出了车辆姿态,主要是位置偏差d和航向角偏差phi,出现偏差就需要矫正,根据物理常识我们知道不可能马上矫正,需要一个矫正的过程,图像采集处理又有一个时间间隔,在这个时间间隔 ...

  3. 无人驾驶虚拟仿真(一)--环境搭建

    简介:安装部署无人驾驶虚拟仿真平台,通过键盘控制仿真小车移动,简单介绍仿真环境切换以及自制方法 基础环境:ubuntu20.04,python3.8.10 1.安装git.pip3 $ sudo ap ...

  4. 无人驾驶虚拟仿真(二)--ROS系统安装

    简介:在ubuntu20.04系统中安装ROS noetic版本 1.安装源 $ sudo sh -c 'echo "deb http://packages.ros.org/ros/ubun ...

  5. 论文阅读——《基于卷积神经网络的车行环境多类障碍物检测与识别》

    近期学习了卷积神经网络相关的知识,在课余时间阅读了一篇有关障碍物检测的硕士生论文,不过就阅读的过程而言,感觉硕士论文有些冗杂,容易让读者抓不到重点,而且篇幅较多,耗费时间有些长,以后阅读论文可以直接从 ...

  6. 无人驾驶虚拟仿真(十三)--图像处理之交通标志牌识别1

            简介:在实际交通地图环境中,我们预设了交通标志牌,可以通过交通标志牌对小车进行更加细致丰富的控制,标志牌形式如下:         每个交通标志牌都是由功能图片+编码图片结合的方式生成 ...

  7. 无人驾驶虚拟仿真(十二)--图像处理之红绿灯识别

    简介:在交通地图中有红绿灯组件,一般放置在T形或者十字路口处,车辆行驶过程中,需要检测红绿灯信号来控制车辆启停,以符合基本的交通规则.红绿灯识别基本分为图像截取.斑点检测.颜色识别三步来实现. 1.新 ...

  8. hough变换直线检测_CV学习笔记(十五):直线检测

    在这一篇文章中我们将学习使用OpenCV中的 HoughLines 函数和 HoughLinesP 函数来检测图像中的直线. 在这个函数中,使用的是霍夫变换(Hough Transform) 这是计算 ...

  9. 无人驾驶虚拟仿真(八)--图像处理之车道线识别3

    简介:在上一节中,我们完成了单张图片车道线的检测,在最终的结果中,可以比较明确的观察出车辆相对车道线的位置,接下来,我们要把这一功能移植到ROS系统中,将小车抓取到的图像都处理成车道线数据,并发布到下 ...

  10. 手把手教用matlab做无人驾驶(二十五)--基于控制障碍函数的MPC(MPC-CBF)

    这边博客主要完成论文的内容:Safety-Critical Model Predictive Control with Discrete-Time Control Barrier Function,论 ...

最新文章

  1. python3 转码的函数_python基础3之文件操作、字符编码解码、函数介绍
  2. Python 四大基本语法
  3. Linux内存描述之概述--Linux内存管理(一)
  4. Win32 ListView控件基本使用
  5. python 链表的基础概念和基础用法
  6. influxdb介绍,安装,使用等(转载:http://www.jianshu.com/p/d2935e99006e)
  7. 【数据结构与算法】之深入解析“24点游戏”的求解思路与算法示例
  8. VC中利用ADO共同实现数据库的操作
  9. Python中base64编码解码结果为b‘xxx‘
  10. 身份证号码正则表达式及校验方法
  11. Dell服务器组建阵列-Raid(有阵列卡)
  12. (区块链溯源)基于Hyperledger Fabric 区块链的危险化学品溯源
  13. 绿卡日记:2020-12-28
  14. proxmox ve 中文社区_基于ProXmoX VE的虚拟化家庭服务器(篇一)—ProXmoX VE 安装及基础配置...
  15. (转)ubuntu软件列表
  16. 融云 | 企业通讯录的设计与实现
  17. 【面试大全-Java】Spring核心问答
  18. 【三角函数】常用的三角函数相关知识
  19. 蚂蚁啃大象之zookeeper学习过程
  20. linux firefox 书签,firefox 的书签在硬盘的那个地方

热门文章

  1. 金蝶盘点机PDA轻松扫码产品入库,生产型企业进销存条码管理软件
  2. flash swf文件 网页播放功能方案实现
  3. 虚拟机(VMware)中windows2003系统服务器的IE无法打开搜索网页
  4. FLASH和EEPROM的区别和扩展
  5. ps去水印教程_Adobe Photoshop CS2去除水印方法 PS去水印教程
  6. C# Winfrom Chart 图表控件 柱状图、折线图
  7. Objective C 的 private
  8. zemax---透镜基础篇
  9. 简易抽签程序(数字滚动 HTML + JavaScript)
  10. Tracert(traceroute)Ping 工作原理分析