Simon Shi的小站

人工智能,机器学习, 强化学习,大模型,自动驾驶

0%

Content

[TOC]

定位技术简介

定位+高精度地图:提供当前位置的静态环境感知( 车道线/交通指示牌/红绿灯/柱子/建筑物/等)
定位+动态物体感知:将感知到的动态物体正确放入静态环境
定位获取位置姿态:用于路径规划/决策

定位技术分类

  • 场景:室内(房间,车库,仓库等)室外()
  • 基于感知模式
    • outside-in: 接收的外界信号包含位置相关信息/ GNSS UWB WIFI Lidar Hdmap Camera-marker(室外街景门牌室内 maker)磁条加marker(规划都做了)扫地机本身贴marker加顶部相机 / (适合测量方程)
    • inside-out:通过自身观察和感受获取位置信息 / IMU magnetometer SLAM VR中的墙面贴marker建图 / (适合状态方程)
  • 基于计算方法
    • 基于信号的定位: GNSS UWB WIFI/几何关系
    • 环境特征匹配: Lidar-HDmap Camera-marker Radar / 需要建图,观测特征与数据库的特征匹配得到当前位姿态
    • 航迹推算:IMUodometry(轮子里程计/视觉里程计SLAM)/根据之前的位姿推断当前的位姿

定位系统的融合

  • 原理:不同源传感器信息通过滤波器(KF, EKF, UKF, PF等)进行融合
  • 典型融合方式:
    • IMU + GNSS :高频率累积误差+低频率高精度 无人机/无人车/导弹/室外
    • GNSS + Lidar-HDMAP/Camera-marker:适合开放环境+适合密集特征环境 无人车/室内外
    • VIO(SLAM+IMU+GNSS) 无人机/无人车/室内外
    • IMU + magnetometer 矫正角度(互补滤波/MadgwickAHRS) 无人机/无人车/室内外

单个定位技术

GNSS

image-20220425004624428

image-20220425004929917

image-20220425010537078

IMU

image-20220425010556563

image-20220425010826600

Lidar / Camera

image-20220425010904835

SLAM

image-20220425011236067

定位融合技术

定位系统的融合

  • 原理:不同源传感器信息通过滤波器(KF, EKF, UKF, PF等)进行融合
  • 典型融合方式:
    • IMU + GNSS :高频率累积误差+低频率高精度 无人机/无人车/导弹/室外
    • GNSS + Lidar-HDMAP/Camera-marker:适合开放环境+适合密集特征环境 无人车/室内外
    • VIO(SLAM+IMU+GNSS) 无人机/无人车/室内外
    • IMU + magnetometer 矫正角度(互补滤波/MadgwickAHRS) 无人机/无人车/室内外

image-20220425143102500

Histogram Filter

image-20220425143146195

image-20220425143802166

image-20220425143848274

image-20220425144543227

Apollo定位方案

image-20220425144503852

image-20220425144704787

image-20220425144932722

开源项目

https://gitee.com/paopaoslam/ORB-SLAM2

[TOC]

王博Kings:无人驾驶系列知识入门到提高7-高精度地图 V2X HD MAP

CSDN self_drive car_学习笔记–第7课:HD MAP高精地图 & V2X

image-20220424013755047

image-20220424013818593

1. OverView

HD AMP

  • 元素信息
  • 点云信息
  • HD地图 = 元素地图 + 点云地图

image-20220424013934991

image-20220424014057581

image-20220424014202348

HD Map VS Navigation Map

image-20220424014247389

LOCALIZATION

image-20220424014343327

Perception 感知

image-20220424014507358

Planning

image-20220424014735268

Apollo HDMap

image-20220424014834961

image-20220424014902996

SLAM

image-20220424014933531

image-20220424015215062

2. OPENDRIVE 开放协议

image-20220424015514699

image-20220424015612168

image-20220424015634216

image-20220424015649077

image-20220424015719101

制图过程和V2X

3. Cloud Point Mapping

3.1 Lidar & Image

image-20220424020049309

3.2 点云匹配

1)依赖库说明
—-OpenCV3:目前最常用也是用途最广的图像处理依赖库,熟悉基本操作,比如cv::Mat、imread
—-Eigen:C++下最常用的矩阵运算库,类似于Matlab,对矩阵的描述和计算都非常方便,任何计算都是矩阵
—-PCL:Point Cloud Library,点云计算库,方便对点云进行操作和可视化

2)安装方法:
—-Eigen库使用源码拷贝的方式或者apt-get安装
—-Opencv安装可以用ppi源来安装,也可以用源码编译安装
—-在Ubuntu下使用apt-get安装PCL
img

3)使用说明

代码库:JointMapping
–cmake .
–make
–./joinMap
–pcl_viewer ./map.pcd

3.3 基础概念

  • 相机内参
  • 相机外参
  • 像素坐标系
  • 刚体运动
  • 坐标系转换
  • 旋转坐标
  • 平移坐标
  • 齐次坐标系,变换矩阵
  • 欧拉角
  • 四元数

3.4 相机模型

1)相机成像的原理是针孔相机模型:

在这里插入图片描述

—-P表示物理世界中的一个点;P’表示成像中模型中的位置;坐标分别为XYZ和X’Y’Z’
—-相似三角形关系:

在这里插入图片描述

2)相机内参
将成像坐标P’切换到像素坐标系中,要进行两步转换:缩放和原点平移
假设P’的像素坐标为[u v]T(表示列矩阵),变换坐标就是:

在这里插入图片描述

把这个形式切换到齐次坐标系:

在这里插入图片描述

这里的K就是我们说的内参矩阵,也就是每个相机需要校准的内参

3)相机外参
注意一下,这里的P是相机坐标系下的位置,而其世界坐标系下的坐标Pw,可以根据旋转平移来得到:
$$
ZP_{w} = K(RP_w + t) = KTP_{w}
$$

—-这里有齐次变换到非齐次坐标的变换
—-因此,相机姿态R,T(t?是不是指的是上面公式的)又称为相机外参
—-外参会随着车辆移动而移动,因此我们高精地图构建过程中就是需要去估计这个外参,同时也是车辆移动轨迹

4)数据结构
–PGM数据格式:Portable Gray Map,最简单的灰度图数据格式,这里我们拿来表示把点云压成平面的深度信息(0-65535),其中0表示没有检测到深度
–png:RGB信息的常用格式
–pose:5组7状态,txt文档,[x y z qx qy qz qw],平移向量和旋转四元数

5)代码示例:
–根据相机内参计算RGB和点云的对应关系
–根据各图相机外参把点云和RGB融合进行图片融合,构成全局地图

【源码是老师的,没有放到云端,下面就是部分截图,仅供参考】

todo

通过该函数,可以获取得到点云图
【下面偷个小懒,截个图算了,哈哈哈】

在这里插入图片描述

在这里插入图片描述

OpenCV 练习

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

4. V2X

image-20220424021237938

image-20220424021247961

image-20220424021307104

image-20220424021336931

符号含义

符号 含义
关联 关联
关联
关联
组合 组合(整体与部分,部分不可以脱离整体存在)翅膀-鸟儿
组合
聚合 聚合(整体与部分,部分可以脱离整体存在)手机–耳机
聚合
依赖 依赖
继承 继承
继承 继承

[TOC]

5.1 基于激光雷达点云的检测算法 (3D检测)

  • 激光雷达点云简介
  • Pixel-Based
  • Voxel-Based
  • Tree-Based
  • Point-Based
  • 实战基于点云的目标检测

0、激光雷达点云简介

什么是激光雷电点云?

image-20220419022248517

常用数据集

image-20220419022639349

KITTI 实战kitti LIDAR点云生成鸟瞰图BEV

image-20220419022502344

点云基础 - 将点云投影到图片上

image-20220419023431055

传统VS深度学习

image-20220420010518793

1、基于像素的点云算法(Pixel-Based)

  • 基本思想:
    • 3D-2D, 三维点云在不同角度的相机投影(映射)
    • 再借助2D图像处理领域成熟的深度学习框架进行分析
  • 典型算法
    • MVCNN, MV3D, AVOD
    • Apollo2.0 SequeezeSeg

MVCNN (分类)

image-20220420011222644

MV3D

image-20220420011317865

AVOD

image-20220420011702183

Feature Extractor

image-20220420011900798

RPN

image-20220420012034009

image-20220420012239576

Apollo2.0

image-20220420012319233

SqueezeSeg

image-20220420012406257

image-20220420012705453

image-20220420012811805

代码实战:[tolearning]

无人驾驶汽车系统入门(二十六)——基于深度学习的实时激光雷达点云目标检测及ROS实现

Ubuntu16.04运行SqueezeSeg_Ros

2、基于体素的点云算法(Voxel-Based)

image-20220420014344009

VoxNet

VoxelNet

= Voxel-Based + Point-Based (局部+全局)

3、基于树的点云算法(Tree-Based)

image-20220420014527963

image-20220420014551923

OctNet

O-CNN

Escape from Cells

4、基于点的点云算法(Point-Based)

  • 对称函数、X变换

image-20220420014643233

PointNet (CVPR2017)

image-20220420015103222

1x3的卷积,实现全连接层

image-20220420015801982

transform_net

image-20220420015935771

PointNet++ (NIPS2017)

image-20220420020202704

image-20220420020408548

PointCNN

image-20220420020528296

核心:X卷积

image-20220420020609633

Frustum-Pointnet

image-20220420020656186

PointRCNN

image-20220420020742927

5.2 Voxelnet

image-20220420020929747

image-20220420021250554

image-20220420021404060

image-20220420021517598

image-20220420021532404

代码结构

image-20220420021615860

效果:

image-20220420021151045

相关资料

zhihu 3D目标检测方法总结

系列零:自动驾驶相关数据集调研总结【附下载地址】(2023更新)

# 系列一:3D目标检测框架综述(OpenPCDet|mmdetection3d|Det3D|Paddle3D)

# 系列二:3D Detection目标检测系列论文总结(2023年更)

# 系列三:3D Segmentation点云语义分割系列论文总结(2023年更)

[TOC]

0. onnx模型准备以及测试图

1. c++使用onnxruntime进行推理

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
#include <opencv2/core.hpp>
#include <opencv2/imgcodecs.hpp>
#include <opencv2/opencv.hpp>
#include <opencv2/highgui.hpp>
#include <opencv2/core/core.hpp>
#include <opencv2/imgproc/imgproc_c.h>
#include <opencv2/dnn.hpp>
#include <iostream>
#include <onnxruntime_cxx_api.h>
#include <assert.h>
#include <vector>
#include <fstream>


using namespace cv; //当定义这一行后,cv::imread可以直接写成imread
using namespace std;
using namespace Ort;
using namespace cv::dnn;

String labels_txt_file = "F:\\Pycharm\\PyCharm_Study\\Others\\c++_learning\\C++_Master\\Onnx\\classification\\classification_classes_ILSVRC2012.txt";
vector<String> readClassNames(); // string对象作为vector对象

// 图像处理 标准化处理
void PreProcess(const Mat& image, Mat& image_blob)
{
Mat input;
image.copyTo(input);


//数据处理 标准化
std::vector<Mat> channels, channel_p;
split(input, channels);
Mat R, G, B;
B = channels.at(0);
G = channels.at(1);
R = channels.at(2);

B = (B / 255. - 0.406) / 0.225;
G = (G / 255. - 0.456) / 0.224;
R = (R / 255. - 0.485) / 0.229;

channel_p.push_back(R);
channel_p.push_back(G);
channel_p.push_back(B);

Mat outt;
merge(channel_p, outt);
image_blob = outt;
}


// 读取txt文件
std::vector<String> readClassNames()
{
std::vector<String> classNames;

std::ifstream fp(labels_txt_file);
if (!fp.is_open())
{
printf("could not open file...\n");
exit(-1);
}
std::string name;
while (!fp.eof())
{
std::getline(fp, name);
if (name.length())
classNames.push_back(name);
}
fp.close();
return classNames;
}



int main() // 返回值为整型带参的main函数. 函数体内使用或不使用argc和argv都可
{

//environment (设置为VERBOSE(ORT_LOGGING_LEVEL_VERBOSE)时,方便控制台输出时看到是使用了cpu还是gpu执行)
Ort::Env env(ORT_LOGGING_LEVEL_WARNING, "OnnxModel");
Ort::SessionOptions session_options;
// 使用1个线程执行op,若想提升速度,增加线程数
session_options.SetIntraOpNumThreads(1);
CUDA加速开启(由于onnxruntime的版本太高,无cuda_provider_factory.h的头文件,加速可以使用onnxruntime V1.8的版本)
//OrtSessionOptionsAppendExecutionProvider_CUDA(session_options, 0);
// ORT_ENABLE_ALL: 启用所有可能的优化
session_options.SetGraphOptimizationLevel(GraphOptimizationLevel::ORT_ENABLE_ALL);

//load model and creat session

#ifdef _WIN32
const wchar_t* model_path = L"F:\\Pycharm\\PyCharm_Study\\Others\\c++_learning\\C++_Master\\Onnx\\classification\\vgg16.onnx";
#else
const char* model_path = "F:\\Pycharm\\PyCharm_Study\\Others\\c++_learning\\C++_Master\\Onnx\\classification\\vgg16.onnx";
#endif

printf("Using Onnxruntime C++ API\n");
Ort::Session session(env, model_path, session_options);
// print model input layer (node names, types, shape etc.)
Ort::AllocatorWithDefaultOptions allocator;


//model info
// 获得模型又多少个输入和输出,一般是指对应网络层的数目
// 一般输入只有图像的话input_nodes为1
size_t num_input_nodes = session.GetInputCount();
// 如果是多输出网络,就会是对应输出的数目
size_t num_output_nodes = session.GetOutputCount();
printf("Number of inputs = %zu\n", num_input_nodes);
printf("Number of output = %zu\n", num_output_nodes);
//获取输入name
const char* input_name = session.GetInputName(0, allocator);
std::cout << "input_name:" << input_name << std::endl;
//获取输出name
const char* output_name = session.GetOutputName(0, allocator);
std::cout << "output_name: " << output_name << std::endl;
// 自动获取维度数量
auto input_dims = session.GetInputTypeInfo(0).GetTensorTypeAndShapeInfo().GetShape();
auto output_dims = session.GetOutputTypeInfo(0).GetTensorTypeAndShapeInfo().GetShape();
std::cout << "input_dims:" << input_dims[0] << std::endl;
std::cout << "output_dims:" << output_dims[0] << std::endl;
std::vector<const char*> input_names{ input_name };
std::vector<const char*> output_names = { output_name };
std::vector<const char*> input_node_names = { "input.1" };
std::vector<const char*> output_node_names = { "70"};


//加载图片
Mat img = imread("F:\\Pycharm\\PyCharm_Study\\Others\\c++_learning\\C++_Master\\Onnx\\classification\\dog.jpg");
Mat det1, det2;
resize(img, det1, Size(256, 256), INTER_AREA);
det1.convertTo(det1, CV_32FC3);
PreProcess(det1, det2); //标准化处理
Mat blob = dnn::blobFromImage(det2, 1., Size(224, 224), Scalar(0, 0, 0), false, true);
printf("Load success!\n");

clock_t startTime, endTime;
//创建输入tensor
auto memory_info = Ort::MemoryInfo::CreateCpu(OrtAllocatorType::OrtArenaAllocator, OrtMemType::OrtMemTypeDefault);
std::vector<Ort::Value> input_tensors;
input_tensors.emplace_back(Ort::Value::CreateTensor<float>(memory_info, blob.ptr<float>(), blob.total(), input_dims.data(), input_dims.size()));
/*cout << int(input_dims.size()) << endl;*/
startTime = clock();

推理(score model & input tensor, get back output tensor)
auto output_tensors = session.Run(Ort::RunOptions{ nullptr }, input_node_names.data(), input_tensors.data(), input_names.size(), output_node_names.data(), output_node_names.size());
endTime = clock();
assert(output_tensors.size() == 1 && output_tensors.front().IsTensor());
//除了第一个节点外,其他参数与原网络对应不上程序就会无法执行
//第二个参数代表输入节点的名称集合
//第四个参数1代表输入层的数目
//第五个参数代表输出节点的名称集合
//最后一个参数代表输出节点的数目
获取输出(Get pointer to output tensor float values)
float* floatarr = output_tensors[0].GetTensorMutableData<float>(); // 也可以使用output_tensors.front(); 获取list中的第一个元素变量 list.pop_front(); 删除list中的第一个位置的元素
// 得到最可能分类输出
Mat newarr = Mat_<double>(1, 1000); //定义一个1*1000的矩阵
for (int i = 0; i < newarr.rows; i++)
{
for (int j = 0; j < newarr.cols; j++) //矩阵列数循环
{
newarr.at<double>(i, j) = floatarr[j];
}
}
/*cout << newarr.size() << endl;*/

vector<String> labels = readClassNames();
for (int n = 0; n < newarr.rows; n++) {
Point classNumber;
double classProb;
Mat probMat = newarr(Rect(0, n, 1000, 1)).clone();
Mat result = probMat.reshape(1, 1);
minMaxLoc(result, NULL, &classProb, NULL, &classNumber);
int classidx = classNumber.x;
printf("\n current image classification : %s, possible : %.2f\n", labels.at(classidx).c_str(), classProb);

// 显示文本
putText(img, labels.at(classidx), Point(10, 20), FONT_HERSHEY_SIMPLEX, 0.6, Scalar(0, 0, 255), 1, 1);
imshow("Image Classification", img);
waitKey(0);
}

计算运行时间
std::cout << "The run time is:" << (double)(endTime - startTime) / CLOCKS_PER_SEC << "s" << std::endl;
printf("Done!\n");
system("pause");
return 0;
}

参考资料

Install ONNX Runtime (ORT)

C++使用onnxruntime/opencv对onnx模型进行推理(附代码)

在C++上利用onnxruntime (CUDA)和 opencv 部署模型onnx

[TOC]

单目跟踪算法:

  • 产生式
  • 鉴别式
  • 基于相关滤波
  • 基于深度学习

6.1 什么是跟踪?

image-20220422012437176

image-20220422012626480

6.2 单目标跟踪

image-20220422012648811

6.2.1 单目标跟踪-产生式模型

image-20220422012909705

Kalman Filter

code: https://github.com/andylei77/kalman_particle_demo

image-20220422013049774

N(均值,协方差)

image-20220422013637320

image-20220422013857445

image-20220422014224130

image-20220422014349327

Particle Filter

image-20220422014550639

6.2.2 单目标跟踪-鉴别式模型

image-20220422014625230

Boosting

MIL

MEDIANFLOW

image-20220422014658024

TLD

  • 跟踪器: 光流
  • 检测器:

image-20220422014742417

OPENCV API

code: https://github.com/andylei77/learnopencv/tree/master/tracking

6.2.3 单目标跟踪-基于相关滤波算法

-

  • MOSSE 评价相似性的滤波算法

CSK

  • CSK方法
    • 密集采样,通过循环矩阵来实现
    • 分类器的学习通过快速傅里叶变换成频域内的计算,不受SVM或Boost等学习方法的限制(什么限制??)。无论线性分类还是核分类,整个学习过程十分高效。
  • 实时性好

image-20220422014833974

MOSSE

image-20220422014901835

KCF

  • 循环矩阵
  • 循环矩阵傅里叶对角化性质–简化计算加速分类器的学习过程
  • 基于HOG特征的分类器(DeepSRDCF:深度学习提取的特征+KCF方法)

image-20220422014917316

GOTURN (深度学习)

https://www.learnopencv.com/goturn-deep-learning-based-object-tracking/

image-20220422014935909

算法综述

数据集;深度学习CNN;CF-相关滤波;其它的

image-20220422014947881

6.3 多目标跟踪

分类方法

  • 按照轨迹形成的时间顺序
    • 在线
    • 离线
  • 按照算法机制
    • 预测校正 / 关联方式
  • 按照算法的数学表示
    • 概率统计最大化 / 确定性推导

image-20220422015001612

Hungarian Algorithm

image-20220422015046313

https://github.com/andylei77/HungarianAlgorithm

image-20220422015113333

实战

发送端:https://github.com/andylei77/object-detector/tree/ROS

  • 基于二分图匹配的多目标跟踪

接受端:https://github.com/andylei77/object-tracker/tree/master/tracker

TVM

[TOC]

训练框架

从训练框架角度来看,Google的TensorFlow和FaceBook的Pytorch是全球主流的深度学习框架,另外亚马逊的MxNet,百度的Paddle,旷视的MegEngine,华为的Mindspore以及一流科技的OneFlow也逐渐在被更多人接受和使用。这么多训练框架,我们究竟应该选择哪个?如果追求易用性,可能你会选择Pytorch,如果追求项目部署落地,可能你会选择TensorFlow,如果追求分布式训练最快可能你会体验OneFlow。

亚马逊的MxNet,

百度的Paddle,

旷视的MegEngine,

华为的Mindspore

ModelScope:阿里达摩院联手中国计算机学会(CCF)

推理框架

前向推理框架,例如在Intel的CPU/GPU上就使用OpenVINO,在Arm的CPU/GPU上使用NCNN/MNN等,在Nvidia GPU上使用TensorRT。

科学家为编译器抽象出了编译器前端,编译器中端,编译器后端等概念,并引入IR (Intermediate Representation)的概率。解释如下:

  • 编译器前端:接收C/C++/Java等不同语言,进行代码生成,吐出IR
  • 编译器中端:接收IR,进行不同编译器后端可以共享的优化,如常量替换,死代码消除,循环优化等,吐出优化后的IR
  • 编译器后端:接收优化后的IR,进行不同硬件的平台相关优化与硬件指令生成,吐出目标文件以LLVM编译器为例子,借用蓝色(知乎ID)大佬的图:

img

深度学习的IR其实就是计算图,所以可以直接叫作Graph IR

img

基于上面深度学习编译器的思想,陈天奇领衔的TVM横空出世。TVM就是一个基于编译优化的深度学习推理框架(暂且说是推理吧,训练功能似乎也开始探索和接入了),我们来看一下TVM的架构图。

img

TVM架构图从这个图中我们可以看到,TVM架构的核心部分就是NNVM编译器(注意一下最新的TVM已经将NNVM升级为了Realy,所以后面提到的Relay也可以看作是NNVM)。NNVM编译器支持直接接收深度学习框架的模型,如TensorFlow/Pytorch/Caffe/MxNet等,同时也支持一些模型的中间格式如ONNX、CoreML。这些模型被NNVM直接编译成Graph IR,然后这些Graph IR被再次优化,吐出优化后的Graph IR,最后对于不同的后端这些Graph IR都会被编译为特定后端可以识别的机器码完成模型推理。比如对于CPU,NNVM就吐出LLVM可以识别的IR,再通过LLVM编译器编译为机器码到CPU上执行。

0x04. 样例展示

在展示样例前说一下我的环境配置,pytorch1.7.0 && TVM 0.8.dev0

这里以Pytorch模型为例,展示一下TVM是如何将Pytorch模型通过Relay(可以理解为NNVM的升级版,)构建TVM中的计算图并进行图优化,最后再通过LLVM编译到Intel CPU上进行执行。最后我们还对比了一下基于TVM优化后的Relay Graph推理速度和直接使用Pytorch模型进行推理的速度。这里是以torchvision中的ResNet18为例子,结果如下:

1
2
Relay top-1 id: 282, classname: tiger cat       Torch top-1 id: 282, classname: tiger cat
Relay time: 1.1846002000000027 seconds Torch time: 2.4181047000000007 seconds

可以看到在预测结果完全一致的情况下,TVM能带来2倍左右的加速。这里简单介绍一下代码的流程。这个代码可以在这里(https://github.com/BBuf/tvm_learn)找到。

0x04.1 导入TVM和Pytorch并加载ResNet18模型
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
import time
import tvm
from tvm import relay
import numpy as np
from tvm.contrib.download import download_testdata
# PyTorch imports
import torch
import torchvision
################################ Load a pretrained PyTorch model
# -------------------------------
model_name = "resnet18"
model = getattr(torchvision.models, model_name)(pretrained=True)
model = model.eval()
# We grab the TorchScripted model via tracing
input_shape = [1, 3, 224, 224]
input_data = torch.randn(input_shape)
scripted_model = torch.jit.trace(model, input_data).eval()

需要注意的是Relay在解析Pytorch模型的时候是解析TorchScript格式的模型,所以这里使用torch.jit.trace跑一遍原始的Pytorch模型并导出TorchScript模型。
0x04.2 载入测试图片

加载一张测试图片,并执行一些后处理过程。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
from PIL import Image
img_url = "https://github.com/dmlc/mxnet.js/blob/main/data/cat.png?raw=true"
img_path = download_testdata(img_url, "cat.png", module="data")
img = Image.open(img_path).resize((224, 224))
# Preprocess the image and convert to tensor
from torchvision import transforms
my_preprocess = transforms.Compose(
[ transforms.Resize(256),
transforms.CenterCrop(224),
transforms.ToTensor(),
transforms.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225]), ])
img = my_preprocess(img)
# 新增Batch维度
img = np.expand_dims(img, 0)
0x04.3 Relay导入TorchScript模型并编译到LLVM后端

接下来我们将PyTorch的graph导入到Relay成为Relay Graph,这里输入层的名字可以任意指定。然后将Gpath使用给定的配置编译到LLVM目标硬件上。

参考资料

「TVM系列教程一」深度学习编译器及TVM 介绍

OpenVINO是英特尔推出的视觉推理加速工具包。应用在Intel的CPU及其GPU上。OpenCV 3.4.1版本加入了英特尔推理引擎后端(英特尔推理引擎是OpenVINO中的一个组件),为英特尔平台的模型推理进行加速。OpenCV新版本(4.3.0)加入nGraph OpenVINO API(2020.03)。
2018 年5月 Intel 发布了 OpenVINO(Open Visual Inferencing and Neural Network Optimization, 开放视觉推理和神经网络优化)工具包,旨在为Intel 计算平台的(基于神经网络的视觉推理任务)提供高性能加速方案,同时支持Intel CPU、 GPU、FPGA 和 Movidius 计算棒等。
————————————————

原文链接:https://blog.csdn.net/weixin_39956356/article/details/107103244

u版YOLOv5目标检测openvino实现