Skip to content
GitLab
Menu
Projects
Groups
Snippets
Loading...
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
Menu
Open sidebar
ModelZoo
yolov5_migraphx
Commits
cfaa9eb1
Commit
cfaa9eb1
authored
Jun 18, 2023
by
shizhm
Browse files
修改yolov5示例为动态shape推理
parent
ca5fdd93
Changes
13
Hide whitespace changes
Inline
Side-by-side
Showing
13 changed files
with
184 additions
and
116 deletions
+184
-116
Doc/Tutorial_Cpp.md
Doc/Tutorial_Cpp.md
+27
-34
Doc/Tutorial_Python.md
Doc/Tutorial_Python.md
+34
-15
Python/YoloV5_infer_migraphx.py
Python/YoloV5_infer_migraphx.py
+47
-24
README.md
README.md
+16
-5
Resource/Configuration.xml
Resource/Configuration.xml
+1
-1
Resource/Images/DynamicPics/image0.jpg
Resource/Images/DynamicPics/image0.jpg
+0
-0
Resource/Images/DynamicPics/image1.jpg
Resource/Images/DynamicPics/image1.jpg
+0
-0
Resource/Images/Result0.jpg
Resource/Images/Result0.jpg
+0
-0
Resource/Images/Result1.jpg
Resource/Images/Result1.jpg
+0
-0
Resource/Models/yolov5s_Nx3xNxN.onnx
Resource/Models/yolov5s_Nx3xNxN.onnx
+0
-0
Src/YOLOV5.cpp
Src/YOLOV5.cpp
+11
-6
Src/YOLOV5.h
Src/YOLOV5.h
+1
-1
Src/main.cpp
Src/main.cpp
+47
-30
No files found.
Doc/Tutorial_Cpp.md
View file @
cfaa9eb1
# YOLOV5检测器
YOLOV5模型是目前工业界使用较多的算法,官方提供了多个不同版本的预训练模型,本份文档主要介绍了如何
将MIGraphX推理结果进行模型初始化、预处理以及后处
理,该示例推理流程对YOLOV5其他版本的模型同样适用。
YOLOV5模型是目前工业界使用较多的算法,官方提供了多个不同版本的预训练模型,本份文档主要介绍了如何
基于migraphx构建YOLOV5动态shape推
理,该示例推理流程对YOLOV5其他版本的模型同样适用。
## 模型简介
...
...
@@ -21,7 +21,7 @@ samples工程中的Resource/Configuration.xml文件的DetectorYOLOV5节点表示
-
ObjectThreshold:用于判断anchor内部是否有物体
```
<ModelPath>"../Resource/Models/YOLOV5s.onnx"</ModelPath>
<ModelPath>"../Resource/Models/YOLOV5s
_Nx3xNxN
.onnx"</ModelPath>
<ClassNameFile>"../Resource/Models/coco.names"</ClassNameFile>
<UseFP16>0</UseFP16><!--是否使用FP16-->
<NumberOfClasses>80</NumberOfClasses><!--类别数(不包括背景类),COCO:80,VOC:20-->
...
...
@@ -32,21 +32,22 @@ samples工程中的Resource/Configuration.xml文件的DetectorYOLOV5节点表示
## 模型初始化
模型初始化首先通过parse_onnx()函数加载YOLOV5的onnx模型,并可以通过program的get_parameter_shapes()函数获取网络的输入属性。完成模型加载之后需要使用compile()方法编译模型,编译模式使用migraphx::gpu::target{}设为GPU模式,编译过程主要基于MIGraphX IR完成各种优化。同时如果需要使用低精度量化进行推理,可以使用quantize_fp16()函数实现。
模型初始化首先通过parse_onnx()函数加载YOLOV5的onnx模型,
本示例构建YOLOV5动态shape推理,所以需要设置模型输入的最大shape,本示例设为{1,3,800,800},
并可以通过program的get_parameter_shapes()函数获取网络的输入属性。完成模型加载之后需要使用compile()方法编译模型,编译模式使用migraphx::gpu::target{}设为GPU模式,编译过程主要基于MIGraphX IR完成各种优化。同时如果需要使用低精度量化进行推理,可以使用quantize_fp16()函数实现。
```
ErrorCode DetectorYOLOV5::Initialize(InitializationParameterOfDetector initializationParameterOfDetector)
{
...
//模型加载
net = migraphx::parse_onnx(modelPath);
migraphx::onnx_options onnx_options;
onnx_options.map_input_dims["images"]={1,3,800,800};
net = migraphx::parse_onnx(modelPath, onnx_options);
LOG_INFO(stdout,"succeed to load model: %s\n",GetFileName(modelPath).c_str());
// 获取模型输入属性
std::
pair
<std::string, migraphx::shape> input
Attribute=*(
net.get_parameter_shapes()
.begin())
;
inputName=input
Attribute.
first;
inputShape=input
Attribute.
second;
std::
unordered_map
<std::string, migraphx::shape> input
Map=
net.get_parameter_shapes();
inputName=input
Map.begin()->
first;
inputShape=input
Map.begin()->
second;
int N=inputShape.lens()[0];
int C=inputShape.lens()[1];
int H=inputShape.lens()[2];
...
...
@@ -64,11 +65,12 @@ ErrorCode DetectorYOLOV5::Initialize(InitializationParameterOfDetector initializ
// 编译模型
migraphx::compile_options options;
options.device_id=0;
// 设置GPU设备,默认为0号设备
options.offload_copy=true;
// 设置offload_copy
options.device_id=0;
options.offload_copy=true;
net.compile(gpuTarget,options);
LOG_INFO(stdout,"succeed to compile model: %s\n",GetFileName(modelPath).c_str());
...
}
```
...
...
@@ -79,19 +81,20 @@ ErrorCode DetectorYOLOV5::Initialize(InitializationParameterOfDetector initializ
1.
转换数据排布为NCHW
2.
归一化[0.0, 1.0]
3.
将输入数据的尺寸变换到YOLOV5输入大小
(1,3,608,608)
3.
将输入数据的尺寸变换到YOLOV5
动态
输入大小
,relInputShape为每次实际inputshape
```
ErrorCode DetectorYOLOV5::Detect(const cv::Mat &srcImage, std::vector<ResultOfDetection> &resultsOfDetection)
ErrorCode DetectorYOLOV5::Detect(const cv::Mat &srcImage,
std::vector<std::size_t> &relInputShape,
std::vector<ResultOfDetection> &resultsOfDetection)
{
...
inputSize = cv::Size(relInputShape[3], relInputShape[2]);
// 预处理并转换为NCHW
cv::Mat inputBlob;
blobFromImage(srcImage, // 输入数据
inputBlob, // 输出数据
1 / 255.0, //归一化
inputSize, //YOLOV5输入尺寸
,本示例为608x608
inputSize, //YOLOV5输入尺寸
Scalar(0, 0, 0), //未减去均值
true, //转换RB通道
false);
...
...
@@ -105,13 +108,13 @@ ErrorCode DetectorYOLOV5::Detect(const cv::Mat &srcImage, std::vector<ResultOfDe
完成图像预处理以及YOLOV5目标检测相关参数设置之后开始执行推理,利用migraphx推理计算得到YOLOV5模型的输出。
```
ErrorCode DetectorYOLOV5::Detect(const cv::Mat &srcImage, std::vector<ResultOfDetection> &resultsOfDetection)
ErrorCode DetectorYOLOV5::Detect(const cv::Mat &srcImage,
std::vector<std::size_t> &relInputShape,
std::vector<ResultOfDetection> &resultsOfDetection)
{
...
// 创建输入数据
std::unordered_map<std::string, migraphx::shape>
inputData;
inputData[inputName]= migraphx::argument{
inputShape
, (float*)inputBlob.data};
migraphx::parameter_map
inputData;
inputData[inputName]= migraphx::argument{
migraphx::shape(inputShape.type(), relInputShape)
, (float*)inputBlob.data};
// 推理
std::vector<migraphx::argument> inferenceResults = net.eval(inputData);
...
...
@@ -137,20 +140,20 @@ YOLOV5的MIGraphX推理结果inferenceResults是一个std::vector< migraphx::arg
-
第二步根据confidenceThreshold阈值进行筛选,当满足第一步阈值anchor的最大置信度得分maxClassScore大于该阈值,则进一步获取当前anchor的坐标信息和预测物体类别信息,小于该阈值则不做处理。
```
ErrorCode DetectorYOLOV5::Detect(const cv::Mat &srcImage, std::vector<ResultOfDetection> &resultsOfDetection)
ErrorCode DetectorYOLOV5::Detect(const cv::Mat &srcImage,
std::vector<std::size_t> &relInputShape,
std::vector<ResultOfDetection> &resultsOfDetection)
{
...
//获取先验框的个数
numProposal=22743
numProposal = outs[0].size[1];
//每个anchor的预测信息数量numOut=85
numOut = outs[0].size[2];
//获取先验框的个数
int
numProposal = outs[0].size[1];
int numOut = outs[0].size[2];
//变换输出的维度
outs[0] = outs[0].reshape(0, numProposal);
//生成先验框
std::vector<float> confidences;
std::vector<cv::Rect> boxes;
std::vector<int> classIds;
//原图尺寸与模型输入尺寸的缩放比例
float ratioh = (float)srcImage.rows / inputSize.height, ratiow = (float)srcImage.cols / inputSize.width;
//计算cx,cy,w,h,box_sore,class_sore
...
...
@@ -158,32 +161,22 @@ ErrorCode DetectorYOLOV5::Detect(const cv::Mat &srcImage, std::vector<ResultOfDe
float* pdata = (float*)outs[0].data;
for (n = 0; n < numProposal; n++)
{
//获取当前anchor是否包含物体的概率值
float boxScores = pdata[4];
//第一次筛选,判断anchor内是否包含物体
if (boxScores > yolov5Parameter.objectThreshold)
{
//获取每个anchor内部预测的80个类别概率信息
cv::Mat scores = outs[0].row(rowInd).colRange(5, numOut);
cv::Point classIdPoint;
double maxClassScore;
//获取80个类别中最大概率值和对应的类别ID
cv::minMaxLoc(scores, 0, &maxClassScore, 0, &classIdPoint);
maxClassScore *= boxScores;
//第二次筛选,判断当前anchor的最大置信度得分是否满足阈值
if (maxClassScore > yolov5Parameter.confidenceThreshold)
{
const int classIdx = classIdPoint.x;
//将每个anchor坐标按缩放比例映射到原图
float cx = pdata[0] * ratiow;
float cy = pdata[1] * ratioh;
float w = pdata[2] * ratiow;
float h = pdata[3] * ratioh;
//获取anchor的左上角坐标
int left = int(cx - 0.5 * w);
int top = int(cy - 0.5 * h);
...
...
@@ -203,7 +196,7 @@ ErrorCode DetectorYOLOV5::Detect(const cv::Mat &srcImage, std::vector<ResultOfDe
为了消除重叠锚框,输出最终的YOLOV5目标检测结果,执行非极大值抑制对筛选之后的anchor进行处理,最后保存检测结果到resultsOfDetection中。
```
ErrorCode DetectorYOLOV5::Detect(const cv::Mat &srcImage, std::vector<ResultOfDetection> &resultsOfDetection)
ErrorCode DetectorYOLOV5::Detect(const cv::Mat &srcImage,
std::vector<std::size_t> &relInputShape,
std::vector<ResultOfDetection> &resultsOfDetection)
{
...
...
...
Doc/Tutorial_Python.md
View file @
cfaa9eb1
# YOLOV5检测器
本份文档主要介绍如何基于MIGraphX构建YOLOV5的Python
推理
示例,根据文档描述可以了解怎样运行该Python示例得到YOLOV5的目标检测结果。
本份文档主要介绍如何基于MIGraphX构建YOLOV5的
动态shape推理
Python示例,根据文档描述可以了解怎样运行该Python示例得到YOLOV5的目标检测结果。
## 模型简介
...
...
@@ -14,7 +14,7 @@ YOLOV5是一种单阶段目标检测算法,该算法在YOLOV4的基础上添
1.
转换数据排布为NCHW
2.
归一化[0.0, 1.0]
3.
调整输入数据的尺寸
为(1,3,608,608)
3.
调整输入数据的尺寸
```
def prepare_input(self, image):
...
...
@@ -34,7 +34,11 @@ def prepare_input(self, image):
return input_img
```
其中模型输入的inputWidth、inputHeight通过migraphx对输入模型进行解析获取,代码位置见YOLOV5类初始化位置。
其中模型输入的inputWidth、inputHeight为每次动态输入shape。
## 推理
执行YOLOV5动态输入推理,首先需要对YOLOV5的动态模型进行解析、编译,与静态推理不同的是,动态shape推理需要设置模型输入的最大shape,本示例设为[1,3,800,800]。
```
class YOLOv5:
...
...
@@ -47,31 +51,33 @@ class YOLOv5:
self.classNames = list(map(lambda x: x.strip(), open('../Resource/Models/coco.names', 'r').readlines()))
# 解析推理模型
self.model = migraphx.parse_onnx(path)
maxInput={"images":[1,3,800,800]}
self.model = migraphx.parse_onnx(path, map_input_dims=maxInput)
# 获取模型的输入name
self.inputName = self.model.get_parameter_names()[0]
# 获取模型的输入尺寸
inputShape = self.model.get_parameter_shapes()[self.inputName].lens()
self.inputHeight = int(inputShape[2])
self.inputWidth = int(inputShape[3])
print("inputName:{0} \ninputMaxShape:{1}".format(self.inputName, inputShape))
# 模型编译
self.model.compile(t=migraphx.get_target("gpu"), device_id=0) # device_id: 设置GPU设备,默认为0号设备
print("Success to compile")
...
```
## 推理
输入图像预处理完成之后开始进行推理,首先需要利用migraphx进行编译,然后对输入数据进行前向计算得到模型的输出result,在detect函数中调用定义的process_output函数对result进行后处理,得到图像中含有物体的anchor坐标信息、类别置信度、类别ID。
模型初始化完成之后开始进行推理,对输入数据进行前向计算得到模型的输出result,在detect函数中调用定义的process_output函数对result进行后处理,得到图像中含有物体的anchor坐标信息、类别置信度、类别ID。
```
def detect(self, image):
# 输入图像预处理
def detect(self, image, input_shape):
self.inputWidth = input_shape[3]
self.inputHeight = input_shape[2]
# 输入图片预处理
input_img = self.prepare_input(image)
# 模型编译
self.model.compile(t=migraphx.get_target("gpu"), device_id=0) # device_id: 设置GPU设备,默认为0号设备
print("Success to compile")
# 执行推理
print("Start to inference")
start = time.time()
result = self.model.run({self.model.get_parameter_names()[0]: input_img})
print('net forward time: {:.4f}'.format(time.time() - start))
...
...
@@ -110,6 +116,19 @@ def process_output(self, output):
return boxes[indices], scores[indices], class_ids[indices]
def extract_boxes(self, predictions):
# 获取anchor的坐标信息
boxes = predictions[:, :4]
# 将anchor的坐标信息映射到输入image
boxes = self.rescale_boxes(boxes)
# 格式转换
boxes_ = np.copy(boxes)
boxes_[..., 0] = boxes[..., 0] - boxes[..., 2] * 0.5
boxes_[..., 1] = boxes[..., 1] - boxes[..., 3] * 0.5
return boxes_
def rescale_boxes(self, boxes):
# 对anchor尺寸进行变换
input_shape = np.array([self.inputWidth, self.inputHeight, self.inputWidth, self.inputHeight])
...
...
Python/YoloV5_infer_migraphx.py
View file @
cfaa9eb1
...
...
@@ -17,26 +17,27 @@ class YOLOv5:
self
.
classNames
=
list
(
map
(
lambda
x
:
x
.
strip
(),
open
(
'../Resource/Models/coco.names'
,
'r'
).
readlines
()))
# 解析推理模型
self
.
model
=
migraphx
.
parse_onnx
(
path
)
maxInput
=
{
"images"
:[
1
,
3
,
800
,
800
]}
self
.
model
=
migraphx
.
parse_onnx
(
path
,
map_input_dims
=
maxInput
)
# 获取模型的输入name
self
.
inputName
=
self
.
model
.
get_parameter_names
()[
0
]
# 获取模型的输入尺寸
inputShape
=
self
.
model
.
get_parameter_shapes
()[
self
.
inputName
].
lens
()
self
.
inputHeight
=
int
(
inputShape
[
2
])
self
.
inputWidth
=
int
(
inputShape
[
3
])
print
(
"inputName:{0}
\n
inputShape:{1}"
.
format
(
self
.
inputName
,
inputShape
))
print
(
"inputName:{0}
\n
inputMaxShape:{1}"
.
format
(
self
.
inputName
,
inputShape
))
# 模型编译
self
.
model
.
compile
(
t
=
migraphx
.
get_target
(
"gpu"
),
device_id
=
0
)
# device_id: 设置GPU设备,默认为0号设备
print
(
"Success to compile"
)
def
detect
(
self
,
image
):
def
detect
(
self
,
image
,
input_shape
):
self
.
inputWidth
=
input_shape
[
3
]
self
.
inputHeight
=
input_shape
[
2
]
# 输入图片预处理
input_img
=
self
.
prepare_input
(
image
)
# 模型编译
self
.
model
.
compile
(
t
=
migraphx
.
get_target
(
"gpu"
),
device_id
=
0
)
# device_id: 设置GPU设备,默认为0号设备
print
(
"Success to compile"
)
# 执行推理
print
(
"Start to inference"
)
start
=
time
.
time
()
result
=
self
.
model
.
run
({
self
.
model
.
get_parameter_names
()[
0
]:
input_img
})
print
(
'net forward time: {:.4f}'
.
format
(
time
.
time
()
-
start
))
...
...
@@ -114,28 +115,50 @@ class YOLOv5:
labelSize
,
baseLine
=
cv2
.
getTextSize
(
label
,
cv2
.
FONT_HERSHEY_SIMPLEX
,
0.5
,
1
)
cv2
.
putText
(
image
,
label
,
(
cx
,
cy
-
10
),
cv2
.
FONT_HERSHEY_SIMPLEX
,
1
,
(
0
,
255
,
255
),
thickness
=
2
)
return
image
def
read_images
(
image_path
):
image_lists
=
[]
for
image_name
in
os
.
listdir
(
image_path
):
image
=
cv2
.
imread
(
image_path
+
"/"
+
image_name
,
1
)
image_lists
.
append
(
image
)
image_lists
.
reverse
()
return
image_lists
if
__name__
==
'__main__'
:
parser
=
argparse
.
ArgumentParser
()
parser
.
add_argument
(
'--imgpath'
,
type
=
str
,
default
=
'../Resource/Images/
bus.jpg
'
,
help
=
"image path"
)
parser
.
add_argument
(
'--modelpath'
,
type
=
str
,
default
=
'../Resource/Models/yolov5s.onnx'
,
help
=
"onnx filepath"
)
parser
.
add_argument
(
'--imgpath'
,
type
=
str
,
default
=
'../Resource/Images/
DynamicPics
'
,
help
=
"image path"
)
parser
.
add_argument
(
'--modelpath'
,
type
=
str
,
default
=
'../Resource/Models/yolov5s
_Nx3xNxN
.onnx'
,
help
=
"onnx filepath"
)
parser
.
add_argument
(
'--objectThreshold'
,
default
=
0.5
,
type
=
float
,
help
=
'class confidence'
)
parser
.
add_argument
(
'--confThreshold'
,
default
=
0.25
,
type
=
float
,
help
=
'class confidence'
)
parser
.
add_argument
(
'--nmsThreshold'
,
default
=
0.5
,
type
=
float
,
help
=
'nms iou thresh'
)
args
=
parser
.
parse_args
()
yolov5_detector
=
YOLOv5
(
args
.
modelpath
,
obj_thres
=
args
.
objectThreshold
,
conf_thres
=
args
.
confThreshold
,
iou_thres
=
args
.
nmsThreshold
)
srcimg
=
cv2
.
imread
(
args
.
imgpath
,
1
)
boxes
,
scores
,
class_ids
=
yolov5_detector
.
detect
(
srcimg
)
dstimg
=
yolov5_detector
.
draw_detections
(
srcimg
,
boxes
,
scores
,
class_ids
)
# 保存检测结果
cv2
.
imwrite
(
"./Result.jpg"
,
dstimg
)
print
(
"Success to save result"
)
# 设置动态输入shape
input_shapes
=
[]
input_shapes
.
append
([
1
,
3
,
416
,
416
])
input_shapes
.
append
([
1
,
3
,
608
,
608
])
# 读取测试图像
image_lists
=
read_images
(
args
.
imgpath
)
# 推理
yolov5_detector
=
YOLOv5
(
args
.
modelpath
,
obj_thres
=
args
.
objectThreshold
,
conf_thres
=
args
.
confThreshold
,
iou_thres
=
args
.
nmsThreshold
)
for
i
,
image
in
enumerate
(
image_lists
):
print
(
"Start to inference image{}"
.
format
(
i
))
boxes
,
scores
,
class_ids
=
yolov5_detector
.
detect
(
image
,
input_shapes
[
i
])
dstimg
=
yolov5_detector
.
draw_detections
(
image
,
boxes
,
scores
,
class_ids
)
# 保存检测结果
result_name
=
"Result{}.jpg"
.
format
(
i
)
cv2
.
imwrite
(
result_name
,
dstimg
)
print
(
"Success to save results"
)
...
...
README.md
View file @
cfaa9eb1
...
...
@@ -43,9 +43,13 @@ pip install -r requirements.txt
### 运行示例
YoloV5模型的推理示例程序是YoloV5_infer_migraphx.py,在Python目录下使用如下命令运行该推理示例:
YoloV5模型的推理示例程序是YoloV5_infer_migraphx.py,
本示例执行YOLOV5动态shape推理,
在Python目录下使用如下命令运行该推理示例:
```
# 开启环境变量
export MIGRAPHX_DYNAMIC_SHAPE=1
# 运行示例
python YoloV5_infer_migraphx.py \
--imgpath 测试图像路径 \
--modelpath onnx模型路径 \
...
...
@@ -56,7 +60,9 @@ python YoloV5_infer_migraphx.py \
程序运行结束会在当前目录生成YoloV5检测结果图像。
<img
src=
"./Resource/Images/Result.jpg"
alt=
"Result_2"
style=
"zoom: 50%;"
/>
<img
src=
"./Resource/Images/Result0.jpg"
alt=
"Result_2"
style=
"zoom: 50%;"
/>
<img
src=
"./Resource/Images/Result1.jpg"
alt=
"Result1"
style=
"zoom: 50%;"
/>
## C++版本推理
...
...
@@ -115,7 +121,7 @@ source ~/.bashrc
### 运行示例
成功编译YoloV5工程后,执行如下命令运行该示例:
成功编译YoloV5工程后,执行如下命令运行
动态shape推理
该示例:
```
# 进入yolov5 migraphx工程根目录
...
...
@@ -124,13 +130,18 @@ cd <path_to_yolov5_migraphx>
# 进入build目录
cd ./build/
# 开启环境变量
export MIGRAPHX_DYNAMIC_SHAPE=1
# 执行示例程序
./YOLOV5
```
程序运行结束会在build目录生成YoloV5检测结果图像。
程序运行结束会在build目录生成YoloV5动态shape推理检测结果图像。
<img
src=
"./Resource/Images/Result0.jpg"
alt=
"Result"
style=
"zoom:50%;"
/>
<img
src=
"./Resource/Images/Result.jpg"
alt=
"Result"
style=
"zoom:50%;"
/>
<img
src=
"./Resource/Images/Result
1
.jpg"
alt=
"Result"
style=
"zoom:50%;"
/>
## 源码仓库及问题反馈
...
...
Resource/Configuration.xml
View file @
cfaa9eb1
...
...
@@ -3,7 +3,7 @@
<!--YOLOV5检测器 -->
<DetectorYOLOV5>
<ModelPath>
"../Resource/Models/yolov5s.onnx"
</ModelPath>
<ModelPath>
"../Resource/Models/yolov5s
_Nx3xNxN
.onnx"
</ModelPath>
<ClassNameFile>
"../Resource/Models/coco.names"
</ClassNameFile>
<UseFP16>
0
</UseFP16>
<!--是否使用FP16-->
<NumberOfClasses>
80
</NumberOfClasses>
<!--类别数(不包括背景类),COCO:80,VOC:20-->
...
...
Resource/Images/DynamicPics/image0.jpg
0 → 100644
View file @
cfaa9eb1
160 KB
Resource/Images/
bus
.jpg
→
Resource/Images/
DynamicPics/image1
.jpg
View file @
cfaa9eb1
File moved
Resource/Images/Result0.jpg
0 → 100644
View file @
cfaa9eb1
183 KB
Resource/Images/Result.jpg
→
Resource/Images/Result
1
.jpg
View file @
cfaa9eb1
File moved
Resource/Models/yolov5s.onnx
→
Resource/Models/yolov5s
_Nx3xNxN
.onnx
View file @
cfaa9eb1
No preview for this file type
Src/YOLOV5.cpp
View file @
cfaa9eb1
...
...
@@ -53,7 +53,10 @@ ErrorCode DetectorYOLOV5::Initialize(InitializationParameterOfDetector initializ
LOG_ERROR
(
stdout
,
"%s not exist!
\n
"
,
modelPath
.
c_str
());
return
MODEL_NOT_EXIST
;
}
net
=
migraphx
::
parse_onnx
(
modelPath
);
migraphx
::
onnx_options
onnx_options
;
onnx_options
.
map_input_dims
[
"images"
]
=
{
1
,
3
,
800
,
800
};
//
net
=
migraphx
::
parse_onnx
(
modelPath
,
onnx_options
);
LOG_INFO
(
stdout
,
"succeed to load model: %s
\n
"
,
GetFileName
(
modelPath
).
c_str
());
// 获取模型输入属性
...
...
@@ -77,7 +80,7 @@ ErrorCode DetectorYOLOV5::Initialize(InitializationParameterOfDetector initializ
// 编译模型
migraphx
::
compile_options
options
;
options
.
device_id
=
0
;
// 设置GPU设备,默认为0号设备
options
.
device_id
=
0
;
options
.
offload_copy
=
true
;
net
.
compile
(
gpuTarget
,
options
);
LOG_INFO
(
stdout
,
"succeed to compile model: %s
\n
"
,
GetFileName
(
modelPath
).
c_str
());
...
...
@@ -103,7 +106,7 @@ ErrorCode DetectorYOLOV5::Initialize(InitializationParameterOfDetector initializ
}
// log
LOG_INFO
(
stdout
,
"InputSize:%dx%d
\n
"
,
inputSize
.
width
,
inputSize
.
height
);
LOG_INFO
(
stdout
,
"Input
Max
Size:%dx%d
\n
"
,
inputSize
.
width
,
inputSize
.
height
);
LOG_INFO
(
stdout
,
"InputName:%s
\n
"
,
inputName
.
c_str
());
LOG_INFO
(
stdout
,
"ConfidenceThreshold:%f
\n
"
,
yolov5Parameter
.
confidenceThreshold
);
LOG_INFO
(
stdout
,
"NMSThreshold:%f
\n
"
,
yolov5Parameter
.
nmsThreshold
);
...
...
@@ -114,7 +117,7 @@ ErrorCode DetectorYOLOV5::Initialize(InitializationParameterOfDetector initializ
}
ErrorCode
DetectorYOLOV5
::
Detect
(
const
cv
::
Mat
&
srcImage
,
std
::
vector
<
ResultOfDetection
>
&
resultsOfDetection
)
ErrorCode
DetectorYOLOV5
::
Detect
(
const
cv
::
Mat
&
srcImage
,
std
::
vector
<
std
::
size_t
>
&
relInputShape
,
std
::
vector
<
ResultOfDetection
>
&
resultsOfDetection
)
{
if
(
srcImage
.
empty
()
||
srcImage
.
type
()
!=
CV_8UC3
)
{
...
...
@@ -122,6 +125,8 @@ ErrorCode DetectorYOLOV5::Detect(const cv::Mat &srcImage, std::vector<ResultOfDe
return
IMAGE_ERROR
;
}
inputSize
=
cv
::
Size
(
relInputShape
[
3
],
relInputShape
[
2
]);
// 数据预处理并转换为NCHW格式
cv
::
Mat
inputBlob
;
cv
::
dnn
::
blobFromImage
(
srcImage
,
...
...
@@ -133,8 +138,8 @@ ErrorCode DetectorYOLOV5::Detect(const cv::Mat &srcImage, std::vector<ResultOfDe
false
);
// 创建输入数据
std
::
unordered_map
<
std
::
string
,
migraphx
::
ar
gument
>
inputData
;
inputData
[
inputName
]
=
migraphx
::
argument
{
inputShape
,
(
float
*
)
inputBlob
.
data
};
migraphx
::
p
ar
ameter_map
inputData
;
inputData
[
inputName
]
=
migraphx
::
argument
{
migraphx
::
shape
(
inputShape
.
type
(),
relInputShape
)
,
(
float
*
)
inputBlob
.
data
};
// 推理
std
::
vector
<
migraphx
::
argument
>
inferenceResults
=
net
.
eval
(
inputData
);
...
...
Src/YOLOV5.h
View file @
cfaa9eb1
...
...
@@ -25,7 +25,7 @@ public:
ErrorCode
Initialize
(
InitializationParameterOfDetector
initializationParameterOfDetector
);
ErrorCode
Detect
(
const
cv
::
Mat
&
srcImage
,
std
::
vector
<
ResultOfDetection
>
&
resultsOfDetection
);
ErrorCode
Detect
(
const
cv
::
Mat
&
srcImage
,
std
::
vector
<
std
::
size_t
>
&
relInputShape
,
std
::
vector
<
ResultOfDetection
>
&
resultsOfDetection
);
private:
cv
::
FileStorage
configurationFile
;
...
...
Src/main.cpp
View file @
cfaa9eb1
...
...
@@ -19,38 +19,55 @@ int main()
}
LOG_INFO
(
stdout
,
"succeed to initialize detector
\n
"
);
// 读取测试图片
cv
::
Mat
srcImage
=
cv
::
imread
(
"../Resource/Images/bus.jpg"
,
1
);
// 推理
std
::
vector
<
migraphxSamples
::
ResultOfDetection
>
predictions
;
double
time1
=
cv
::
getTickCount
();
detector
.
Detect
(
srcImage
,
predictions
);
double
time2
=
cv
::
getTickCount
();
double
elapsedTime
=
(
time2
-
time1
)
*
1000
/
cv
::
getTickFrequency
();
LOG_INFO
(
stdout
,
"inference time:%f ms
\n
"
,
elapsedTime
);
// 获取推理结果
LOG_INFO
(
stdout
,
"========== Detection Results ==========
\n
"
);
for
(
int
i
=
0
;
i
<
predictions
.
size
();
++
i
)
// 读取测试图像
std
::
vector
<
cv
::
Mat
>
srcImages
;
cv
::
String
folder
=
"../Resource/Images/DynamicPics"
;
std
::
vector
<
cv
::
String
>
imagePathList
;
cv
::
glob
(
folder
,
imagePathList
);
for
(
int
i
=
0
;
i
<
imagePathList
.
size
();
++
i
)
{
migraphxSamples
::
ResultOfDetection
result
=
predictions
[
i
];
cv
::
rectangle
(
srcImage
,
result
.
boundingBox
,
cv
::
Scalar
(
0
,
255
,
255
),
2
);
std
::
string
label
=
cv
::
format
(
"%.2f"
,
result
.
confidence
);
label
=
result
.
className
+
" "
+
label
;
int
left
=
predictions
[
i
].
boundingBox
.
x
;
int
top
=
predictions
[
i
].
boundingBox
.
y
;
int
baseLine
;
cv
::
Size
labelSize
=
cv
::
getTextSize
(
label
,
cv
::
FONT_HERSHEY_SIMPLEX
,
0.5
,
1
,
&
baseLine
);
top
=
max
(
top
,
labelSize
.
height
);
cv
::
putText
(
srcImage
,
label
,
cv
::
Point
(
left
,
top
-
10
),
cv
::
FONT_HERSHEY_SIMPLEX
,
1
,
cv
::
Scalar
(
0
,
255
,
255
),
2
);
LOG_INFO
(
stdout
,
"box:%d %d %d %d,label:%d,confidence:%f
\n
"
,
predictions
[
i
].
boundingBox
.
x
,
predictions
[
i
].
boundingBox
.
y
,
predictions
[
i
].
boundingBox
.
width
,
predictions
[
i
].
boundingBox
.
height
,
predictions
[
i
].
classID
,
predictions
[
i
].
confidence
);
cv
::
Mat
srcImage
=
cv
::
imread
(
imagePathList
[
i
],
1
);
srcImages
.
push_back
(
srcImage
);
}
// 设置动态推理shape
std
::
vector
<
std
::
vector
<
std
::
size_t
>>
inputShapes
;
inputShapes
.
push_back
({
1
,
3
,
416
,
416
});
inputShapes
.
push_back
({
1
,
3
,
608
,
608
});
for
(
int
i
=
0
;
i
<
srcImages
.
size
();
++
i
)
{
// 推理
std
::
vector
<
migraphxSamples
::
ResultOfDetection
>
predictions
;
double
time1
=
cv
::
getTickCount
();
detector
.
Detect
(
srcImages
[
i
],
inputShapes
[
i
],
predictions
);
double
time2
=
cv
::
getTickCount
();
double
elapsedTime
=
(
time2
-
time1
)
*
1000
/
cv
::
getTickFrequency
();
LOG_INFO
(
stdout
,
"inference image%d time:%f ms
\n
"
,
i
,
elapsedTime
);
// 获取推理结果
LOG_INFO
(
stdout
,
"========== Detection Image%d Results ==========
\n
"
,
i
);
for
(
int
j
=
0
;
j
<
predictions
.
size
();
++
j
)
{
migraphxSamples
::
ResultOfDetection
result
=
predictions
[
j
];
cv
::
rectangle
(
srcImages
[
i
],
result
.
boundingBox
,
cv
::
Scalar
(
0
,
255
,
255
),
2
);
std
::
string
label
=
cv
::
format
(
"%.2f"
,
result
.
confidence
);
label
=
result
.
className
+
" "
+
label
;
int
left
=
predictions
[
j
].
boundingBox
.
x
;
int
top
=
predictions
[
j
].
boundingBox
.
y
;
int
baseLine
;
cv
::
Size
labelSize
=
cv
::
getTextSize
(
label
,
cv
::
FONT_HERSHEY_SIMPLEX
,
0.5
,
1
,
&
baseLine
);
top
=
max
(
top
,
labelSize
.
height
);
cv
::
putText
(
srcImages
[
i
],
label
,
cv
::
Point
(
left
,
top
-
10
),
cv
::
FONT_HERSHEY_SIMPLEX
,
1
,
cv
::
Scalar
(
0
,
255
,
255
),
2
);
LOG_INFO
(
stdout
,
"box:%d %d %d %d,label:%d,confidence:%f
\n
"
,
predictions
[
j
].
boundingBox
.
x
,
predictions
[
j
].
boundingBox
.
y
,
predictions
[
j
].
boundingBox
.
width
,
predictions
[
j
].
boundingBox
.
height
,
predictions
[
j
].
classID
,
predictions
[
j
].
confidence
);
}
std
::
string
imgName
=
cv
::
format
(
"Result%d.jpg"
,
i
);
cv
::
imwrite
(
imgName
,
srcImages
[
i
]);
LOG_INFO
(
stdout
,
"Detection results have been saved to ./Result%d.jpg
\n
"
,
i
);
}
cv
::
imwrite
(
"Result.jpg"
,
srcImage
);
LOG_INFO
(
stdout
,
"Detection results have been saved to ./Result.jpg
\n
"
);
return
0
;
}
\ No newline at end of file
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
.
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment