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
yaoht
YOLOX_MiGraphX
Commits
a5e2341e
"vscode:/vscode.git/clone" did not exist on "47c77112227f6276fff51fd229cc98569edb713b"
Commit
a5e2341e
authored
Jan 08, 2024
by
yaoht
Browse files
fix cpp inputdata channel range problem
parent
e80d6c72
Changes
5
Hide whitespace changes
Inline
Side-by-side
Showing
5 changed files
with
309 additions
and
442 deletions
+309
-442
Python/__pycache__/coco_classes.cpython-37.pyc
Python/__pycache__/coco_classes.cpython-37.pyc
+0
-0
Python/__pycache__/coco_classes.cpython-38.pyc
Python/__pycache__/coco_classes.cpython-38.pyc
+0
-0
Src/YOLOX.cpp
Src/YOLOX.cpp
+231
-293
Src/YOLOX.h
Src/YOLOX.h
+33
-30
Src/main.cpp
Src/main.cpp
+45
-119
No files found.
Python/__pycache__/coco_classes.cpython-37.pyc
0 → 100644
View file @
a5e2341e
File added
Python/__pycache__/coco_classes.cpython-38.pyc
0 → 100644
View file @
a5e2341e
File added
Src/YOLOX.cpp
View file @
a5e2341e
#include <Filesystem.h>
#include <SimpleLog.h>
#include <YOLOX.h>
#include <YOLOX.h>
#include <migraphx/onnx.hpp>
#include <migraphx/gpu/target.hpp>
#include <migraphx/gpu/target.hpp>
#include <migraphx/onnx.hpp>
#include <migraphx/quantization.hpp>
#include <migraphx/quantization.hpp>
#include <Filesystem.h>
#include <SimpleLog.h>
#define INPUT_W (640)
#define INPUT_H (640)
namespace
migraphxSamples
{
DetectorYOLOX
::
DetectorYOLOX
()
{
}
namespace
migraphxSamples
{
DetectorYOLOX
::~
DetectorYOLOX
()
DetectorYOLOX
::
DetectorYOLOX
()
{}
{
configurationFile
.
release
();
DetectorYOLOX
::~
DetectorYOLOX
()
{
configurationFile
.
release
();
}
}
ErrorCode
DetectorYOLOX
::
Initialize
(
InitializationParameterOfDetector
initializationParameterOfDetector
,
bool
dynamic
)
ErrorCode
DetectorYOLOX
::
Initialize
(
{
InitializationParameterOfDetector
initializationParameterOfDetector
)
{
// 读取配置文件
// 读取配置文件
std
::
string
configFilePath
=
initializationParameterOfDetector
.
configFilePath
;
std
::
string
configFilePath
=
i
f
(
Exists
(
configFilePath
)
==
false
)
i
nitializationParameterOfDetector
.
configFilePath
;
{
if
(
!
Exists
(
configFilePath
))
{
LOG_ERROR
(
stdout
,
"no configuration file!
\n
"
);
LOG_ERROR
(
stdout
,
"no configuration file!
\n
"
);
return
CONFIG_FILE_NOT_EXIST
;
return
CONFIG_FILE_NOT_EXIST
;
}
}
if
(
!
configurationFile
.
open
(
configFilePath
,
cv
::
FileStorage
::
READ
))
if
(
!
configurationFile
.
open
(
configFilePath
,
cv
::
FileStorage
::
READ
))
{
{
LOG_ERROR
(
stdout
,
"fail to open configuration file
\n
"
);
LOG_ERROR
(
stdout
,
"fail to open configuration file
\n
"
);
return
FAIL_TO_OPEN_CONFIG_FILE
;
return
FAIL_TO_OPEN_CONFIG_FILE
;
}
}
LOG_INFO
(
stdout
,
"succeed to open configuration file
\n
"
);
LOG_INFO
(
stdout
,
"succeed to open configuration file
\n
"
);
// 获取配置文件参数
// 获取配置文件参数
cv
::
FileNode
netNode
=
configurationFile
[
"DetectorYOLOX"
];
cv
::
FileNode
netNode
=
configurationFile
[
"DetectorYOLOX"
];
if
(
dynamic
)
modelPath
=
(
std
::
string
)
netNode
[
"ModelPathStatic"
];
{
std
::
string
pathOfClassNameFile
=
(
std
::
string
)
netNode
[
"ClassNameFile"
];
modelPath
=
(
std
::
string
)
netNode
[
"ModelPathDynamic"
];
}
else
{
modelPath
=
(
std
::
string
)
netNode
[
"ModelPathStatic"
];
}
std
::
string
pathOfClassNameFile
=
(
std
::
string
)
netNode
[
"ClassNameFile"
];
yoloxParameter
.
confidenceThreshold
=
(
float
)
netNode
[
"ConfidenceThreshold"
];
yoloxParameter
.
confidenceThreshold
=
(
float
)
netNode
[
"ConfidenceThreshold"
];
yoloxParameter
.
nmsThreshold
=
(
float
)
netNode
[
"NMSThreshold"
];
yoloxParameter
.
nmsThreshold
=
(
float
)
netNode
[
"NMSThreshold"
];
yoloxParameter
.
objectThreshold
=
(
float
)
netNode
[
"ObjectThreshold"
];
yoloxParameter
.
objectThreshold
=
(
float
)
netNode
[
"ObjectThreshold"
];
yoloxParameter
.
numberOfClasses
=
(
int
)
netNode
[
"NumberOfClasses"
];
yoloxParameter
.
numberOfClasses
=
(
int
)
netNode
[
"NumberOfClasses"
];
useFP16
=
(
bool
)(
int
)
netNode
[
"UseFP16"
];
useFP16
=
(
bool
)(
int
)
netNode
[
"UseFP16"
];
if
(
dynamic
)
// 加载模型
{
if
(
!
Exists
(
modelPath
))
{
// 加载模型
LOG_ERROR
(
stdout
,
"%s not exist!
\n
"
,
modelPath
.
c_str
());
if
(
Exists
(
modelPath
)
==
false
)
return
MODEL_NOT_EXIST
;
{
LOG_ERROR
(
stdout
,
"%s not exist!
\n
"
,
modelPath
.
c_str
());
return
MODEL_NOT_EXIST
;
}
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
::
cout
<<
"inputs:"
<<
std
::
endl
;
std
::
unordered_map
<
std
::
string
,
migraphx
::
shape
>
inputs
=
net
.
get_inputs
();
for
(
auto
i
:
inputs
)
{
std
::
cout
<<
i
.
first
<<
":"
<<
i
.
second
<<
std
::
endl
;
}
std
::
cout
<<
"outputs:"
<<
std
::
endl
;
std
::
unordered_map
<
std
::
string
,
migraphx
::
shape
>
outputs
=
net
.
get_outputs
();
for
(
auto
i
:
outputs
)
{
std
::
cout
<<
i
.
first
<<
":"
<<
i
.
second
<<
std
::
endl
;
}
inputName
=
inputs
.
begin
()
->
first
;
inputShape
=
inputs
.
begin
()
->
second
;
int
N
=
inputShape
.
lens
()[
0
];
int
C
=
inputShape
.
lens
()[
1
];
int
H
=
inputShape
.
lens
()[
2
];
int
W
=
inputShape
.
lens
()[
3
];
inputSize
=
cv
::
Size
(
W
,
H
);
// log
LOG_INFO
(
stdout
,
"InputMaxSize:%dx%d
\n
"
,
inputSize
.
width
,
inputSize
.
height
);
}
}
else
net
=
migraphx
::
parse_onnx
(
modelPath
);
{
LOG_INFO
(
stdout
,
"succeed to load model: %s
\n
"
,
// 加载模型
GetFileName
(
modelPath
).
c_str
());
if
(
Exists
(
modelPath
)
==
false
)
{
// 获取模型输入/输出节点信息
LOG_ERROR
(
stdout
,
"%s not exist!
\n
"
,
modelPath
.
c_str
());
std
::
cout
<<
"inputs:"
<<
std
::
endl
;
return
MODEL_NOT_EXIST
;
std
::
unordered_map
<
std
::
string
,
migraphx
::
shape
>
inputs
=
net
.
get_inputs
();
}
for
(
auto
i
:
inputs
)
{
net
=
migraphx
::
parse_onnx
(
modelPath
);
std
::
cout
<<
i
.
first
<<
":"
<<
i
.
second
<<
std
::
endl
;
LOG_INFO
(
stdout
,
"succeed to load model: %s
\n
"
,
GetFileName
(
modelPath
).
c_str
());
// 获取模型输入/输出节点信息
std
::
cout
<<
"inputs:"
<<
std
::
endl
;
std
::
unordered_map
<
std
::
string
,
migraphx
::
shape
>
inputs
=
net
.
get_inputs
();
for
(
auto
i
:
inputs
)
{
std
::
cout
<<
i
.
first
<<
":"
<<
i
.
second
<<
std
::
endl
;
}
std
::
cout
<<
"outputs:"
<<
std
::
endl
;
std
::
unordered_map
<
std
::
string
,
migraphx
::
shape
>
outputs
=
net
.
get_outputs
();
for
(
auto
i
:
outputs
)
{
std
::
cout
<<
i
.
first
<<
":"
<<
i
.
second
<<
std
::
endl
;
}
inputName
=
inputs
.
begin
()
->
first
;
inputShape
=
inputs
.
begin
()
->
second
;
int
N
=
inputShape
.
lens
()[
0
];
int
C
=
inputShape
.
lens
()[
1
];
int
H
=
inputShape
.
lens
()[
2
];
int
W
=
inputShape
.
lens
()[
3
];
inputSize
=
cv
::
Size
(
W
,
H
);
// log
LOG_INFO
(
stdout
,
"InputSize:%dx%d
\n
"
,
inputSize
.
width
,
inputSize
.
height
);
}
}
std
::
cout
<<
"outputs:"
<<
std
::
endl
;
LOG_INFO
(
stdout
,
"InputName:%s
\n
"
,
inputName
.
c_str
());
std
::
unordered_map
<
std
::
string
,
migraphx
::
shape
>
outputs
=
LOG_INFO
(
stdout
,
"ConfidenceThreshold:%f
\n
"
,
yoloxParameter
.
confidenceThreshold
);
net
.
get_outputs
();
LOG_INFO
(
stdout
,
"NMSThreshold:%f
\n
"
,
yoloxParameter
.
nmsThreshold
);
for
(
auto
i
:
outputs
)
{
LOG_INFO
(
stdout
,
"objectThreshold:%f
\n
"
,
yoloxParameter
.
objectThreshold
);
std
::
cout
<<
i
.
first
<<
":"
<<
i
.
second
<<
std
::
endl
;
LOG_INFO
(
stdout
,
"NumberOfClasses:%d
\n
"
,
yoloxParameter
.
numberOfClasses
);
}
inputName
=
inputs
.
begin
()
->
first
;
inputShape
=
inputs
.
begin
()
->
second
;
int
N
=
inputShape
.
lens
()[
0
];
int
C
=
inputShape
.
lens
()[
1
];
int
H
=
inputShape
.
lens
()[
2
];
int
W
=
inputShape
.
lens
()[
3
];
inputSize
=
cv
::
Size
(
W
,
H
);
// log
LOG_INFO
(
stdout
,
"InputSize:%dx%d
\n
"
,
inputSize
.
width
,
inputSize
.
height
);
LOG_INFO
(
stdout
,
"InputName:%s
\n
"
,
inputName
.
c_str
());
LOG_INFO
(
stdout
,
"ConfidenceThreshold:%f
\n
"
,
yoloxParameter
.
confidenceThreshold
);
LOG_INFO
(
stdout
,
"NMSThreshold:%f
\n
"
,
yoloxParameter
.
nmsThreshold
);
LOG_INFO
(
stdout
,
"objectThreshold:%f
\n
"
,
yoloxParameter
.
objectThreshold
);
LOG_INFO
(
stdout
,
"NumberOfClasses:%d
\n
"
,
yoloxParameter
.
numberOfClasses
);
// 设置模型为GPU模式
// 设置模型为GPU模式
migraphx
::
target
gpuTarget
=
migraphx
::
gpu
::
target
{};
migraphx
::
target
gpuTarget
=
migraphx
::
gpu
::
target
{};
// 量化
// 量化
if
(
useFP16
)
if
(
useFP16
)
{
{
migraphx
::
quantize_fp16
(
net
);
migraphx
::
quantize_fp16
(
net
);
}
}
// 编译模型
// 编译模型
migraphx
::
compile_options
options
;
migraphx
::
compile_options
options
;
options
.
device_id
=
0
;
options
.
device_id
=
0
;
options
.
offload_copy
=
true
;
options
.
offload_copy
=
true
;
net
.
compile
(
gpuTarget
,
options
);
net
.
compile
(
gpuTarget
,
options
);
LOG_INFO
(
stdout
,
"succeed to compile model: %s
\n
"
,
GetFileName
(
modelPath
).
c_str
());
LOG_INFO
(
stdout
,
"succeed to compile model: %s
\n
"
,
GetFileName
(
modelPath
).
c_str
());
// warm up
// warm up
std
::
unordered_map
<
std
::
string
,
migraphx
::
argument
>
inputData
;
std
::
unordered_map
<
std
::
string
,
migraphx
::
argument
>
inputData
;
inputData
[
inputName
]
=
migraphx
::
argument
{
inputShape
};
inputData
[
inputName
]
=
migraphx
::
argument
{
inputShape
};
net
.
eval
(
inputData
);
net
.
eval
(
inputData
);
// 读取类别名
// 读取类别名
if
(
!
pathOfClassNameFile
.
empty
())
if
(
!
pathOfClassNameFile
.
empty
())
{
{
std
::
ifstream
classNameFile
(
pathOfClassNameFile
);
std
::
ifstream
classNameFile
(
pathOfClassNameFile
);
std
::
string
line
;
std
::
string
line
;
while
(
getline
(
classNameFile
,
line
))
while
(
getline
(
classNameFile
,
line
))
{
{
classNames
.
push_back
(
line
);
classNames
.
push_back
(
line
);
}
}
}
}
else
{
else
{
classNames
.
resize
(
yoloxParameter
.
numberOfClasses
);
classNames
.
resize
(
yoloxParameter
.
numberOfClasses
);
}
}
return
SUCCESS
;
return
SUCCESS
;
}
}
void
DetectorYOLOX
::
generate_grids_and_stride
(
std
::
vector
<
int
>&
strides
,
std
::
vector
<
GridAndStride
>&
grid_strides
)
void
DetectorYOLOX
::
generate_grids_and_stride
(
{
std
::
vector
<
int
>
&
strides
,
std
::
vector
<
GridAndStride
>
&
grid_strides
,
for
(
auto
stride
:
strides
)
cv
::
Size
inputSize
)
{
{
for
(
auto
stride
:
strides
)
{
int
num_grid_y
=
INPUT_H
/
stride
;
int
num_grid_y
=
inputSize
.
height
/
stride
;
int
num_grid_x
=
INPUT_W
/
stride
;
int
num_grid_x
=
inputSize
.
width
/
stride
;
for
(
int
g1
=
0
;
g1
<
num_grid_y
;
g1
++
)
for
(
int
g1
=
0
;
g1
<
num_grid_y
;
g1
++
)
{
{
for
(
int
g0
=
0
;
g0
<
num_grid_x
;
g0
++
)
{
for
(
int
g0
=
0
;
g0
<
num_grid_x
;
g0
++
)
{
grid_strides
.
push_back
((
GridAndStride
){
g0
,
g1
,
stride
});
grid_strides
.
push_back
((
GridAndStride
){
g0
,
g1
,
stride
});
}
}
}
}
}
}
}
}
void
DetectorYOLOX
::
generate_yolox_proposals
(
std
::
vector
<
GridAndStride
>
grid_strides
,
float
*
feat_blob
,
float
prob_threshold
,
std
::
vector
<
Object
>&
objects
)
void
DetectorYOLOX
::
generate_yolox_proposals
(
{
std
::
vector
<
GridAndStride
>
grid_strides
,
float
*
feat_blob
,
float
prob_threshold
,
std
::
vector
<
Object
>
&
objects
)
{
const
int
num_anchors
=
grid_strides
.
size
();
const
int
num_anchors
=
grid_strides
.
size
();
float
max_box_objectness
=
0
;
float
max_box_objectness
=
0
;
for
(
int
anchor_idx
=
0
;
anchor_idx
<
num_anchors
;
anchor_idx
++
)
for
(
int
anchor_idx
=
0
;
anchor_idx
<
num_anchors
;
anchor_idx
++
)
{
{
const
int
grid0
=
grid_strides
[
anchor_idx
].
grid0
;
const
int
grid0
=
grid_strides
[
anchor_idx
].
grid0
;
const
int
grid1
=
grid_strides
[
anchor_idx
].
grid1
;
const
int
grid1
=
grid_strides
[
anchor_idx
].
grid1
;
const
int
stride
=
grid_strides
[
anchor_idx
].
stride
;
const
int
stride
=
grid_strides
[
anchor_idx
].
stride
;
...
@@ -207,58 +138,57 @@ void DetectorYOLOX::generate_yolox_proposals(std::vector<GridAndStride> grid_str
...
@@ -207,58 +138,57 @@ void DetectorYOLOX::generate_yolox_proposals(std::vector<GridAndStride> grid_str
const
int
basic_pos
=
anchor_idx
*
(
yoloxParameter
.
numberOfClasses
+
5
);
const
int
basic_pos
=
anchor_idx
*
(
yoloxParameter
.
numberOfClasses
+
5
);
// yolox/models/yolo_head.py decode logic
// yolox/models/yolo_head.py decode logic
float
x_center
=
(
feat_blob
[
basic_pos
+
0
]
+
grid0
)
*
stride
;
float
x_center
=
(
feat_blob
[
basic_pos
+
0
]
+
grid0
)
*
stride
;
float
y_center
=
(
feat_blob
[
basic_pos
+
1
]
+
grid1
)
*
stride
;
float
y_center
=
(
feat_blob
[
basic_pos
+
1
]
+
grid1
)
*
stride
;
float
w
=
exp
(
feat_blob
[
basic_pos
+
2
])
*
stride
;
float
w
=
exp
(
feat_blob
[
basic_pos
+
2
])
*
stride
;
float
h
=
exp
(
feat_blob
[
basic_pos
+
3
])
*
stride
;
float
h
=
exp
(
feat_blob
[
basic_pos
+
3
])
*
stride
;
float
x0
=
x_center
-
w
*
0.5
f
;
float
x0
=
x_center
-
w
*
0.5
f
;
float
y0
=
y_center
-
h
*
0.5
f
;
float
y0
=
y_center
-
h
*
0.5
f
;
float
box_objectness
=
feat_blob
[
basic_pos
+
4
];
float
box_objectness
=
feat_blob
[
basic_pos
+
4
];
max_box_objectness
=
box_objectness
>
max_box_objectness
?
box_objectness
:
max_box_objectness
;
max_box_objectness
=
box_objectness
>
max_box_objectness
?
box_objectness
:
max_box_objectness
;
float
max_box_cls_score
=
0
;
float
max_box_cls_score
=
0
;
int
max_score_class_idx
=
0
;
int
max_score_class_idx
=
0
;
for
(
int
class_idx
=
0
;
class_idx
<
yoloxParameter
.
numberOfClasses
;
class_idx
++
)
for
(
int
class_idx
=
0
;
class_idx
<
yoloxParameter
.
numberOfClasses
;
{
class_idx
++
)
{
float
box_cls_score
=
feat_blob
[
basic_pos
+
5
+
class_idx
];
float
box_cls_score
=
feat_blob
[
basic_pos
+
5
+
class_idx
];
if
(
box_cls_score
>
max_box_cls_score
)
if
(
box_cls_score
>
max_box_cls_score
)
{
{
max_box_cls_score
=
box_cls_score
;
max_box_cls_score
=
box_cls_score
;
max_score_class_idx
=
class_idx
;
max_score_class_idx
=
class_idx
;
}
}
}
// class loop
}
// class loop
float
box_prob
=
box_objectness
*
max_box_cls_score
;
float
box_prob
=
box_objectness
*
max_box_cls_score
;
if
(
box_objectness
>
yoloxParameter
.
objectThreshold
&&
box_prob
>
yoloxParameter
.
confidenceThreshold
)
if
(
box_objectness
>
yoloxParameter
.
objectThreshold
&&
{
box_prob
>
yoloxParameter
.
confidenceThreshold
)
{
Object
obj
;
Object
obj
;
obj
.
rect
.
x
=
x0
;
obj
.
rect
.
x
=
x0
;
obj
.
rect
.
y
=
y0
;
obj
.
rect
.
y
=
y0
;
obj
.
rect
.
width
=
w
;
obj
.
rect
.
width
=
w
;
obj
.
rect
.
height
=
h
;
obj
.
rect
.
height
=
h
;
obj
.
label
=
max_score_class_idx
;
obj
.
label
=
max_score_class_idx
;
obj
.
prob
=
box_prob
;
obj
.
prob
=
box_prob
;
objects
.
push_back
(
obj
);
objects
.
push_back
(
obj
);
}
}
}
// point anchor loop
}
// point anchor loop
}
}
void
DetectorYOLOX
::
qsort_descent_inplace
(
std
::
vector
<
Object
>
&
faceobjects
,
int
left
,
int
right
)
void
DetectorYOLOX
::
qsort_descent_inplace
(
std
::
vector
<
Object
>
&
faceobjects
,
{
int
left
,
int
right
)
{
int
i
=
left
;
int
i
=
left
;
int
j
=
right
;
int
j
=
right
;
float
p
=
faceobjects
[(
left
+
right
)
/
2
].
prob
;
float
p
=
faceobjects
[(
left
+
right
)
/
2
].
prob
;
while
(
i
<=
j
)
while
(
i
<=
j
)
{
{
while
(
faceobjects
[
i
].
prob
>
p
)
while
(
faceobjects
[
i
].
prob
>
p
)
i
++
;
i
++
;
while
(
faceobjects
[
j
].
prob
<
p
)
while
(
faceobjects
[
j
].
prob
<
p
)
j
--
;
j
--
;
if
(
i
<=
j
)
if
(
i
<=
j
)
{
{
// swap
// swap
std
::
swap
(
faceobjects
[
i
],
faceobjects
[
j
]);
std
::
swap
(
faceobjects
[
i
],
faceobjects
[
j
]);
...
@@ -267,53 +197,52 @@ void DetectorYOLOX::qsort_descent_inplace(std::vector<Object>& faceobjects, int
...
@@ -267,53 +197,52 @@ void DetectorYOLOX::qsort_descent_inplace(std::vector<Object>& faceobjects, int
}
}
}
}
#pragma omp parallel sections
#pragma omp parallel sections
{
{
#pragma omp section
#pragma omp section
{
{
if
(
left
<
j
)
qsort_descent_inplace
(
faceobjects
,
left
,
j
);
if
(
left
<
j
)
qsort_descent_inplace
(
faceobjects
,
left
,
j
);
}
}
#pragma omp section
#pragma omp section
{
{
if
(
i
<
right
)
qsort_descent_inplace
(
faceobjects
,
i
,
right
);
if
(
i
<
right
)
qsort_descent_inplace
(
faceobjects
,
i
,
right
);
}
}
}
}
}
}
void
DetectorYOLOX
::
qsort_descent_inplace
(
std
::
vector
<
Object
>&
objects
)
void
DetectorYOLOX
::
qsort_descent_inplace
(
std
::
vector
<
Object
>
&
objects
)
{
{
if
(
objects
.
empty
())
if
(
objects
.
empty
())
return
;
return
;
qsort_descent_inplace
(
objects
,
0
,
objects
.
size
()
-
1
);
qsort_descent_inplace
(
objects
,
0
,
objects
.
size
()
-
1
);
}
}
inline
float
DetectorYOLOX
::
intersection_area
(
const
Object
&
a
,
const
Object
&
b
)
inline
float
DetectorYOLOX
::
intersection_area
(
const
Object
&
a
,
{
const
Object
&
b
)
{
cv
::
Rect_
<
float
>
inter
=
a
.
rect
&
b
.
rect
;
cv
::
Rect_
<
float
>
inter
=
a
.
rect
&
b
.
rect
;
return
inter
.
area
();
return
inter
.
area
();
}
}
void
DetectorYOLOX
::
nms_sorted_bboxes
(
const
std
::
vector
<
Object
>&
faceobjects
,
std
::
vector
<
int
>&
picked
,
float
nms_threshold
)
void
DetectorYOLOX
::
nms_sorted_bboxes
(
const
std
::
vector
<
Object
>
&
faceobjects
,
{
std
::
vector
<
int
>
&
picked
,
float
nms_threshold
)
{
picked
.
clear
();
picked
.
clear
();
const
int
n
=
faceobjects
.
size
();
const
int
n
=
faceobjects
.
size
();
std
::
vector
<
float
>
areas
(
n
);
std
::
vector
<
float
>
areas
(
n
);
for
(
int
i
=
0
;
i
<
n
;
i
++
)
for
(
int
i
=
0
;
i
<
n
;
i
++
)
{
{
areas
[
i
]
=
faceobjects
[
i
].
rect
.
area
();
areas
[
i
]
=
faceobjects
[
i
].
rect
.
area
();
}
}
for
(
int
i
=
0
;
i
<
n
;
i
++
)
for
(
int
i
=
0
;
i
<
n
;
i
++
)
{
{
const
Object
&
a
=
faceobjects
[
i
];
const
Object
&
a
=
faceobjects
[
i
];
int
keep
=
1
;
int
keep
=
1
;
for
(
int
j
=
0
;
j
<
(
int
)
picked
.
size
();
j
++
)
for
(
int
j
=
0
;
j
<
(
int
)
picked
.
size
();
j
++
)
{
{
const
Object
&
b
=
faceobjects
[
picked
[
j
]];
const
Object
&
b
=
faceobjects
[
picked
[
j
]];
// intersection over union
// intersection over union
float
inter_area
=
intersection_area
(
a
,
b
);
float
inter_area
=
intersection_area
(
a
,
b
);
...
@@ -328,49 +257,51 @@ void DetectorYOLOX::nms_sorted_bboxes(const std::vector<Object>& faceobjects, st
...
@@ -328,49 +257,51 @@ void DetectorYOLOX::nms_sorted_bboxes(const std::vector<Object>& faceobjects, st
}
}
}
}
void
DetectorYOLOX
::
decode_outputs
(
float
*
prob
,
std
::
vector
<
Object
>&
objects
,
float
scalew
,
float
scaleh
,
const
int
img_w
,
const
int
img_h
)
{
void
DetectorYOLOX
::
decode_outputs
(
float
*
prob
,
std
::
vector
<
Object
>
&
objects
,
std
::
vector
<
Object
>
proposals
;
float
scalew
,
float
scaleh
,
const
int
img_w
,
std
::
vector
<
int
>
strides
=
{
8
,
16
,
32
};
const
int
img_h
,
cv
::
Size
inputSize
)
{
std
::
vector
<
GridAndStride
>
grid_strides
;
std
::
vector
<
Object
>
proposals
;
generate_grids_and_stride
(
strides
,
grid_strides
);
std
::
vector
<
int
>
strides
=
{
8
,
16
,
32
};
generate_yolox_proposals
(
grid_strides
,
prob
,
yoloxParameter
.
confidenceThreshold
,
proposals
);
std
::
vector
<
GridAndStride
>
grid_strides
;
std
::
cout
<<
"num of boxes before nms: "
<<
proposals
.
size
()
<<
std
::
endl
;
generate_grids_and_stride
(
strides
,
grid_strides
,
inputSize
);
generate_yolox_proposals
(
grid_strides
,
prob
,
qsort_descent_inplace
(
proposals
);
yoloxParameter
.
confidenceThreshold
,
proposals
);
std
::
cout
<<
"num of boxes before nms: "
<<
proposals
.
size
()
<<
std
::
endl
;
std
::
vector
<
int
>
picked
;
nms_sorted_bboxes
(
proposals
,
picked
,
yoloxParameter
.
nmsThreshold
);
qsort_descent_inplace
(
proposals
);
std
::
vector
<
int
>
picked
;
int
count
=
picked
.
size
();
nms_sorted_bboxes
(
proposals
,
picked
,
yoloxParameter
.
nmsThreshold
);
std
::
cout
<<
"num of boxes: "
<<
count
<<
std
::
endl
;
int
count
=
picked
.
size
();
objects
.
resize
(
count
);
std
::
cout
<<
"num of boxes: "
<<
count
<<
std
::
endl
;
for
(
int
i
=
0
;
i
<
count
;
i
++
)
{
objects
.
resize
(
count
);
objects
[
i
]
=
proposals
[
picked
[
i
]];
for
(
int
i
=
0
;
i
<
count
;
i
++
)
{
objects
[
i
]
=
proposals
[
picked
[
i
]];
// adjust offset to original unpadded
float
x0
=
(
objects
[
i
].
rect
.
x
)
/
scalew
;
// adjust offset to original unpadded
float
y0
=
(
objects
[
i
].
rect
.
y
)
/
scaleh
;
float
x0
=
(
objects
[
i
].
rect
.
x
)
/
scalew
;
float
x1
=
(
objects
[
i
].
rect
.
x
+
objects
[
i
].
rect
.
width
)
/
scalew
;
float
y0
=
(
objects
[
i
].
rect
.
y
)
/
scaleh
;
float
y1
=
(
objects
[
i
].
rect
.
y
+
objects
[
i
].
rect
.
height
)
/
scaleh
;
float
x1
=
(
objects
[
i
].
rect
.
x
+
objects
[
i
].
rect
.
width
)
/
scalew
;
float
y1
=
(
objects
[
i
].
rect
.
y
+
objects
[
i
].
rect
.
height
)
/
scaleh
;
// clip
x0
=
std
::
max
(
std
::
min
(
x0
,
(
float
)(
img_w
-
1
)),
0.
f
);
// clip
y0
=
std
::
max
(
std
::
min
(
y0
,
(
float
)(
img_h
-
1
)),
0.
f
);
x0
=
std
::
max
(
std
::
min
(
x0
,
(
float
)(
img_w
-
1
)),
0.
f
);
x1
=
std
::
max
(
std
::
min
(
x1
,
(
float
)(
img_w
-
1
)),
0.
f
);
y0
=
std
::
max
(
std
::
min
(
y0
,
(
float
)(
img_h
-
1
)),
0.
f
);
y1
=
std
::
max
(
std
::
min
(
y1
,
(
float
)(
img_h
-
1
)),
0.
f
);
x1
=
std
::
max
(
std
::
min
(
x1
,
(
float
)(
img_w
-
1
)),
0.
f
);
y1
=
std
::
max
(
std
::
min
(
y1
,
(
float
)(
img_h
-
1
)),
0.
f
);
objects
[
i
].
rect
.
x
=
x0
;
objects
[
i
].
rect
.
y
=
y0
;
objects
[
i
].
rect
.
x
=
x0
;
objects
[
i
].
rect
.
width
=
x1
-
x0
;
objects
[
i
].
rect
.
y
=
y0
;
objects
[
i
].
rect
.
height
=
y1
-
y0
;
objects
[
i
].
rect
.
width
=
x1
-
x0
;
}
objects
[
i
].
rect
.
height
=
y1
-
y0
;
}
}
}
void
meshgrid
(
const
cv
::
Range
&
x_range
,
const
cv
::
Range
&
y_range
,
cv
::
Mat
&
xv
,
cv
::
Mat
&
yv
)
{
void
meshgrid
(
const
cv
::
Range
&
x_range
,
const
cv
::
Range
&
y_range
,
cv
::
Mat
&
xv
,
cv
::
Mat
&
yv
)
{
// 初始化矩阵大小
// 初始化矩阵大小
int
rows
=
y_range
.
end
-
y_range
.
start
+
1
;
int
rows
=
y_range
.
end
-
y_range
.
start
+
1
;
int
cols
=
x_range
.
end
-
x_range
.
start
+
1
;
int
cols
=
x_range
.
end
-
x_range
.
start
+
1
;
...
@@ -391,7 +322,8 @@ void meshgrid(const cv::Range& x_range, const cv::Range& y_range, cv::Mat& xv, c
...
@@ -391,7 +322,8 @@ void meshgrid(const cv::Range& x_range, const cv::Range& y_range, cv::Mat& xv, c
cv
::
Mat
demo_postprocess
(
cv
::
Mat
outputs
,
cv
::
Size
img_size
,
bool
p6
=
false
)
{
cv
::
Mat
demo_postprocess
(
cv
::
Mat
outputs
,
cv
::
Size
img_size
,
bool
p6
=
false
)
{
std
::
vector
<
cv
::
Mat
>
grids
;
std
::
vector
<
cv
::
Mat
>
grids
;
std
::
vector
<
cv
::
Mat
>
expanded_strides
;
std
::
vector
<
cv
::
Mat
>
expanded_strides
;
std
::
vector
<
int
>
strides
=
p6
?
std
::
vector
<
int
>
{
8
,
16
,
32
,
64
}
:
std
::
vector
<
int
>
{
8
,
16
,
32
};
std
::
vector
<
int
>
strides
=
p6
?
std
::
vector
<
int
>
{
8
,
16
,
32
,
64
}
:
std
::
vector
<
int
>
{
8
,
16
,
32
};
std
::
vector
<
int
>
hsizes
,
wsizes
;
std
::
vector
<
int
>
hsizes
,
wsizes
;
for
(
int
stride
:
strides
)
{
for
(
int
stride
:
strides
)
{
...
@@ -409,7 +341,8 @@ cv::Mat demo_postprocess(cv::Mat outputs, cv::Size img_size, bool p6 = false) {
...
@@ -409,7 +341,8 @@ cv::Mat demo_postprocess(cv::Mat outputs, cv::Size img_size, bool p6 = false) {
}
}
grids
.
push_back
(
grid
);
grids
.
push_back
(
grid
);
cv
::
Mat
expanded_stride
=
cv
::
Mat
::
ones
(
hsizes
[
i
]
*
wsizes
[
i
],
1
,
CV_32F
)
*
strides
[
i
];
cv
::
Mat
expanded_stride
=
cv
::
Mat
::
ones
(
hsizes
[
i
]
*
wsizes
[
i
],
1
,
CV_32F
)
*
strides
[
i
];
expanded_strides
.
push_back
(
expanded_stride
);
expanded_strides
.
push_back
(
expanded_stride
);
}
}
...
@@ -420,12 +353,18 @@ cv::Mat demo_postprocess(cv::Mat outputs, cv::Size img_size, bool p6 = false) {
...
@@ -420,12 +353,18 @@ cv::Mat demo_postprocess(cv::Mat outputs, cv::Size img_size, bool p6 = false) {
cv
::
Mat
outputs_clone
=
outputs
.
clone
();
cv
::
Mat
outputs_clone
=
outputs
.
clone
();
for
(
int
i
=
0
;
i
<
outputs_clone
.
rows
;
++
i
)
{
for
(
int
i
=
0
;
i
<
outputs_clone
.
rows
;
++
i
)
{
outputs_clone
.
at
<
float
>
(
i
,
0
)
=
(
outputs
.
at
<
float
>
(
i
,
0
)
+
grids_concatenated
.
at
<
float
>
(
i
,
0
))
*
outputs_clone
.
at
<
float
>
(
i
,
0
)
=
expanded_strides_concatenated
.
at
<
float
>
(
i
,
0
);
(
outputs
.
at
<
float
>
(
i
,
0
)
+
grids_concatenated
.
at
<
float
>
(
i
,
0
))
*
outputs_clone
.
at
<
float
>
(
i
,
1
)
=
(
outputs
.
at
<
float
>
(
i
,
1
)
+
grids_concatenated
.
at
<
float
>
(
i
,
1
))
*
expanded_strides_concatenated
.
at
<
float
>
(
i
,
0
);
expanded_strides_concatenated
.
at
<
float
>
(
i
,
0
);
outputs_clone
.
at
<
float
>
(
i
,
1
)
=
outputs_clone
.
at
<
float
>
(
i
,
2
)
=
exp
(
outputs
.
at
<
float
>
(
i
,
2
))
*
expanded_strides_concatenated
.
at
<
float
>
(
i
,
0
);
(
outputs
.
at
<
float
>
(
i
,
1
)
+
grids_concatenated
.
at
<
float
>
(
i
,
1
))
*
outputs_clone
.
at
<
float
>
(
i
,
3
)
=
exp
(
outputs
.
at
<
float
>
(
i
,
3
))
*
expanded_strides_concatenated
.
at
<
float
>
(
i
,
0
);
expanded_strides_concatenated
.
at
<
float
>
(
i
,
0
);
outputs_clone
.
at
<
float
>
(
i
,
2
)
=
exp
(
outputs
.
at
<
float
>
(
i
,
2
))
*
expanded_strides_concatenated
.
at
<
float
>
(
i
,
0
);
outputs_clone
.
at
<
float
>
(
i
,
3
)
=
exp
(
outputs
.
at
<
float
>
(
i
,
3
))
*
expanded_strides_concatenated
.
at
<
float
>
(
i
,
0
);
}
}
return
outputs_clone
;
return
outputs_clone
;
...
@@ -448,17 +387,23 @@ std::vector<int> nms(cv::Mat boxes, cv::Mat scores, float nms_thr) {
...
@@ -448,17 +387,23 @@ std::vector<int> nms(cv::Mat boxes, cv::Mat scores, float nms_thr) {
// 根据分数排序的索引
// 根据分数排序的索引
std
::
vector
<
int
>
order
(
scores
.
rows
);
std
::
vector
<
int
>
order
(
scores
.
rows
);
std
::
iota
(
order
.
begin
(),
order
.
end
(),
0
);
std
::
iota
(
order
.
begin
(),
order
.
end
(),
0
);
std
::
sort
(
order
.
begin
(),
order
.
end
(),
[
&
scores
](
int
i
,
int
j
)
{
return
scores
.
at
<
float
>
(
i
)
>
scores
.
at
<
float
>
(
j
);
});
std
::
sort
(
order
.
begin
(),
order
.
end
(),
[
&
scores
](
int
i
,
int
j
)
{
return
scores
.
at
<
float
>
(
i
)
>
scores
.
at
<
float
>
(
j
);
});
// 执行 NMS
// 执行 NMS
while
(
!
order
.
empty
())
{
while
(
!
order
.
empty
())
{
int
i
=
order
[
0
];
int
i
=
order
[
0
];
keep
.
push_back
(
i
);
keep
.
push_back
(
i
);
float
xx1
=
std
::
max
(
boxes
.
at
<
float
>
(
i
,
0
),
boxes
.
at
<
float
>
(
order
[
1
],
0
));
float
xx1
=
float
yy1
=
std
::
max
(
boxes
.
at
<
float
>
(
i
,
1
),
boxes
.
at
<
float
>
(
order
[
1
],
1
));
std
::
max
(
boxes
.
at
<
float
>
(
i
,
0
),
boxes
.
at
<
float
>
(
order
[
1
],
0
));
float
xx2
=
std
::
min
(
boxes
.
at
<
float
>
(
i
,
2
),
boxes
.
at
<
float
>
(
order
[
1
],
2
));
float
yy1
=
float
yy2
=
std
::
min
(
boxes
.
at
<
float
>
(
i
,
3
),
boxes
.
at
<
float
>
(
order
[
1
],
3
));
std
::
max
(
boxes
.
at
<
float
>
(
i
,
1
),
boxes
.
at
<
float
>
(
order
[
1
],
1
));
float
xx2
=
std
::
min
(
boxes
.
at
<
float
>
(
i
,
2
),
boxes
.
at
<
float
>
(
order
[
1
],
2
));
float
yy2
=
std
::
min
(
boxes
.
at
<
float
>
(
i
,
3
),
boxes
.
at
<
float
>
(
order
[
1
],
3
));
float
w
=
std
::
max
(
0.0
f
,
xx2
-
xx1
+
1
);
float
w
=
std
::
max
(
0.0
f
,
xx2
-
xx1
+
1
);
float
h
=
std
::
max
(
0.0
f
,
yy2
-
yy1
+
1
);
float
h
=
std
::
max
(
0.0
f
,
yy2
-
yy1
+
1
);
...
@@ -478,13 +423,15 @@ std::vector<int> nms(cv::Mat boxes, cv::Mat scores, float nms_thr) {
...
@@ -478,13 +423,15 @@ std::vector<int> nms(cv::Mat boxes, cv::Mat scores, float nms_thr) {
return
keep
;
return
keep
;
}
}
cv
::
Mat
multiclass_nms_class_agnostic
(
cv
::
Mat
boxes
,
cv
::
Mat
scores
,
float
nms_thr
,
float
score_thr
)
{
cv
::
Mat
multiclass_nms_class_agnostic
(
cv
::
Mat
boxes
,
cv
::
Mat
scores
,
float
nms_thr
,
float
score_thr
)
{
// 获取每个框的最高分数的索引和分数
// 获取每个框的最高分数的索引和分数
cv
::
Mat
cls_inds
;
cv
::
Mat
cls_inds
;
cv
::
Mat
cls_scores
=
cv
::
Mat
::
zeros
(
scores
.
rows
,
1
,
CV_32F
);
cv
::
Mat
cls_scores
=
cv
::
Mat
::
zeros
(
scores
.
rows
,
1
,
CV_32F
);
for
(
int
i
=
0
;
i
<
scores
.
rows
;
++
i
)
{
for
(
int
i
=
0
;
i
<
scores
.
rows
;
++
i
)
{
int
max_idx
;
int
max_idx
;
// cv::minMaxIdx(scores.row(i), nullptr, &cls_scores.at<float>(i), nullptr, &max_idx);
// cv::minMaxIdx(scores.row(i), nullptr, &cls_scores.at<float>(i),
// nullptr, &max_idx);
double
cls_score
;
double
cls_score
;
cv
::
minMaxIdx
(
scores
.
row
(
i
),
nullptr
,
&
cls_score
,
nullptr
,
&
max_idx
);
cv
::
minMaxIdx
(
scores
.
row
(
i
),
nullptr
,
&
cls_score
,
nullptr
,
&
max_idx
);
cls_scores
.
at
<
float
>
(
i
)
=
static_cast
<
float
>
(
cls_score
);
cls_scores
.
at
<
float
>
(
i
)
=
static_cast
<
float
>
(
cls_score
);
...
@@ -495,18 +442,19 @@ cv::Mat multiclass_nms_class_agnostic(cv::Mat boxes, cv::Mat scores, float nms_t
...
@@ -495,18 +442,19 @@ cv::Mat multiclass_nms_class_agnostic(cv::Mat boxes, cv::Mat scores, float nms_t
// 过滤掉低于阈值的分数
// 过滤掉低于阈值的分数
cv
::
Mat
valid_score_mask
=
cls_scores
>
score_thr
;
cv
::
Mat
valid_score_mask
=
cls_scores
>
score_thr
;
if
(
cv
::
countNonZero
(
valid_score_mask
)
==
0
)
{
if
(
cv
::
countNonZero
(
valid_score_mask
)
==
0
)
{
return
cv
::
Mat
();
// 如果没有有效的分数,返回空矩阵
return
cv
::
Mat
();
// 如果没有有效的分数,返回空矩阵
}
}
// 保留有效分数对应的框和类别索引
// 保留有效分数对应的框和类别索引
cv
::
Mat
valid_scores
=
cls_scores
(
valid_score_mask
);
cv
::
Mat
valid_scores
=
cls_scores
(
valid_score_mask
);
cv
::
Mat
valid_boxes
=
boxes
.
rowRange
(
0
,
boxes
.
rows
).
clone
();
// 复制框数据以便后续修改
cv
::
Mat
valid_boxes
=
boxes
.
rowRange
(
0
,
boxes
.
rows
).
clone
();
// 复制框数据以便后续修改
cv
::
Mat
valid_cls_inds
=
cls_inds
(
valid_score_mask
);
cv
::
Mat
valid_cls_inds
=
cls_inds
(
valid_score_mask
);
// 应用 NMS 算法
// 应用 NMS 算法
std
::
vector
<
int
>
keep
=
nms
(
valid_boxes
,
valid_scores
,
nms_thr
);
std
::
vector
<
int
>
keep
=
nms
(
valid_boxes
,
valid_scores
,
nms_thr
);
if
(
keep
.
empty
())
{
if
(
keep
.
empty
())
{
return
cv
::
Mat
();
// 如果没有保留的框,返回空矩阵
return
cv
::
Mat
();
// 如果没有保留的框,返回空矩阵
}
}
// 按行组合保留的框、分数和类别索引
// 按行组合保留的框、分数和类别索引
...
@@ -521,11 +469,11 @@ cv::Mat multiclass_nms_class_agnostic(cv::Mat boxes, cv::Mat scores, float nms_t
...
@@ -521,11 +469,11 @@ cv::Mat multiclass_nms_class_agnostic(cv::Mat boxes, cv::Mat scores, float nms_t
return
dets
;
return
dets
;
}
}
ErrorCode
ErrorCode
DetectorYOLOX
::
Detect
(
const
cv
::
Mat
&
srcImage
,
std
::
vector
<
std
::
size_t
>
&
relInputShape
,
std
::
vector
<
ResultOfDetection
>
&
resultsOfDetection
,
bool
dynamic
)
DetectorYOLOX
::
Detect
(
const
cv
::
Mat
&
srcImage
,
{
const
std
::
vector
<
std
::
size_t
>
&
relInputShape
,
if
(
srcImage
.
empty
()
||
srcImage
.
type
()
!=
CV_8UC3
)
std
::
vector
<
ResultOfDetection
>
&
resultsOfDetection
)
{
{
if
(
srcImage
.
empty
()
||
srcImage
.
type
()
!=
CV_8UC3
)
{
LOG_ERROR
(
stdout
,
"image error!
\n
"
);
LOG_ERROR
(
stdout
,
"image error!
\n
"
);
return
IMAGE_ERROR
;
return
IMAGE_ERROR
;
}
}
...
@@ -533,65 +481,55 @@ ErrorCode DetectorYOLOX::Detect(const cv::Mat &srcImage, std::vector<std::size_t
...
@@ -533,65 +481,55 @@ ErrorCode DetectorYOLOX::Detect(const cv::Mat &srcImage, std::vector<std::size_t
// 数据预处理并转换为NCHW格式
// 数据预处理并转换为NCHW格式
inputSize
=
cv
::
Size
(
relInputShape
[
3
],
relInputShape
[
2
]);
inputSize
=
cv
::
Size
(
relInputShape
[
3
],
relInputShape
[
2
]);
cv
::
Mat
inputBlob
;
cv
::
Mat
inputBlob
;
cv
::
dnn
::
blobFromImage
(
srcImage
,
cv
::
dnn
::
blobFromImage
(
srcImage
,
inputBlob
,
1
,
inputSize
,
inputBlob
,
cv
::
Scalar
(
0
,
0
,
0
),
false
,
false
);
// 1 / 255.0,
float
ratio
=
std
::
min
(
inputSize
.
width
/
srcImage
.
rows
,
1
,
inputSize
.
height
/
srcImage
.
cols
);
inputSize
,
cv
::
Scalar
(
0
,
0
,
0
),
true
,
false
);
float
ratio
=
std
::
min
(
inputSize
.
width
/
srcImage
.
rows
,
inputSize
.
height
/
srcImage
.
cols
);
// 创建输入数据
// 创建输入数据
migraphx
::
parameter_map
inputData
;
migraphx
::
parameter_map
inputData
;
if
(
dynamic
)
{
inputData
[
inputName
]
=
inputData
[
inputName
]
=
migraphx
::
argument
{
migraphx
::
shape
(
inputShape
.
type
(),
relInputShape
),
(
float
*
)
inputBlob
.
data
};
migraphx
::
argument
{
inputShape
,
(
float
*
)
inputBlob
.
data
};
}
else
{
inputData
[
inputName
]
=
migraphx
::
argument
{
inputShape
,
(
float
*
)
inputBlob
.
data
};
}
// 推理
// 推理
std
::
vector
<
migraphx
::
argument
>
inferenceResults
=
net
.
eval
(
inputData
);
std
::
vector
<
migraphx
::
argument
>
inferenceResults
=
net
.
eval
(
inputData
);
// 获取推理结果
// 获取推理结果
std
::
vector
<
cv
::
Mat
>
outs
;
std
::
vector
<
cv
::
Mat
>
outs
;
migraphx
::
argument
result
=
inferenceResults
[
0
];
migraphx
::
argument
result
=
inferenceResults
[
0
];
// 转换为cv::Mat
// 转换为cv::Mat
migraphx
::
shape
outputShape
=
result
.
get_shape
();
migraphx
::
shape
outputShape
=
result
.
get_shape
();
std
::
cout
<<
outputShape
.
lens
()[
2
]
<<
std
::
endl
;
int
shape
[]
=
{
outputShape
.
lens
()[
0
],
outputShape
.
lens
()[
1
],
int
shape
[]
=
{
outputShape
.
lens
()[
0
],
outputShape
.
lens
()[
1
],
outputShape
.
lens
()[
2
]};
outputShape
.
lens
()[
2
]};
cv
::
Mat
out
(
3
,
shape
,
CV_32F
);
cv
::
Mat
out
(
3
,
shape
,
CV_32F
);
memcpy
(
out
.
data
,
result
.
data
(),
sizeof
(
float
)
*
outputShape
.
elements
());
memcpy
(
out
.
data
,
result
.
data
(),
sizeof
(
float
)
*
outputShape
.
elements
());
outs
.
push_back
(
out
);
outs
.
push_back
(
out
);
//获取先验框的个数
//
获取先验框的个数
int
numProposal
=
outs
[
0
].
size
[
1
];
int
numProposal
=
outs
[
0
].
size
[
1
];
int
numOut
=
outs
[
0
].
size
[
2
];
int
numOut
=
outs
[
0
].
size
[
2
];
//变换输出的维度
//
变换输出的维度
outs
[
0
]
=
outs
[
0
].
reshape
(
0
,
numProposal
);
outs
[
0
]
=
outs
[
0
].
reshape
(
0
,
numProposal
);
float
*
prob
=
(
float
*
)
outs
[
0
].
data
;
float
*
prob
=
(
float
*
)
outs
[
0
].
data
;
std
::
vector
<
Object
>
objects
;
std
::
vector
<
Object
>
objects
;
float
scalew
=
inputSize
.
width
/
(
srcImage
.
cols
*
1.0
);
float
scalew
=
inputSize
.
width
/
(
srcImage
.
cols
*
1.0
);
float
scaleh
=
inputSize
.
height
/
(
srcImage
.
rows
*
1.0
);
float
scaleh
=
inputSize
.
height
/
(
srcImage
.
rows
*
1.0
);
decode_outputs
(
prob
,
objects
,
scalew
,
scaleh
,
srcImage
.
cols
,
srcImage
.
rows
);
decode_outputs
(
prob
,
objects
,
scalew
,
scaleh
,
srcImage
.
cols
,
srcImage
.
rows
,
inputSize
);
for
(
size_t
i
=
0
;
i
<
objects
.
size
();
++
i
)
for
(
size_t
i
=
0
;
i
<
objects
.
size
();
++
i
)
{
{
ResultOfDetection
result
;
ResultOfDetection
result
;
result
.
boundingBox
=
objects
[
i
].
rect
;
result
.
boundingBox
=
objects
[
i
].
rect
;
result
.
confidence
=
objects
[
i
].
prob
;
// confidence
result
.
confidence
=
objects
[
i
].
prob
;
// confidence
result
.
classID
=
objects
[
i
].
label
;
// label
result
.
classID
=
objects
[
i
].
label
;
// label
result
.
className
=
classNames
[
objects
[
i
].
label
];
result
.
className
=
classNames
[
objects
[
i
].
label
];
resultsOfDetection
.
push_back
(
result
);
resultsOfDetection
.
push_back
(
result
);
}
}
return
SUCCESS
;
return
SUCCESS
;
}
}
}
}
// namespace migraphxSamples
Src/YOLOX.h
View file @
a5e2341e
#ifndef __DETECTOR_YOLOX_H__
#ifndef __DETECTOR_YOLOX_H__
#define __DETECTOR_YOLOX_H__
#define __DETECTOR_YOLOX_H__
#include <migraphx/program.hpp>
#include <CommonDefinition.h>
#include <CommonDefinition.h>
#include <migraphx/program.hpp>
namespace
migraphxSamples
namespace
migraphxSamples
{
{
typedef
struct
_YOLOXParameter
typedef
struct
_YOLOXParameter
{
{
int
numberOfClasses
;
int
numberOfClasses
;
float
confidenceThreshold
;
float
confidenceThreshold
;
float
nmsThreshold
;
float
nmsThreshold
;
float
objectThreshold
;
float
objectThreshold
;
}
YOLOXParameter
;
}
YOLOXParameter
;
struct
Object
struct
Object
{
{
cv
::
Rect_
<
float
>
rect
;
cv
::
Rect_
<
float
>
rect
;
int
label
;
int
label
;
float
prob
;
float
prob
;
};
};
struct
GridAndStride
struct
GridAndStride
{
{
int
grid0
;
int
grid0
;
int
grid1
;
int
grid1
;
int
stride
;
int
stride
;
};
};
class
DetectorYOLOX
class
DetectorYOLOX
{
{
public:
public:
DetectorYOLOX
();
DetectorYOLOX
();
~
DetectorYOLOX
();
ErrorCode
Initialize
(
InitializationParameterOfDetector
initializationParameterOfDetector
,
bool
dynamic
);
~
DetectorYOLOX
();
void
decode_outputs
(
float
*
prob
,
std
::
vector
<
Object
>&
objects
,
float
scalew
,
float
scaleh
,
const
int
img_w
,
const
int
img_h
);
void
generate_grids_and_stride
(
std
::
vector
<
int
>&
strides
,
std
::
vector
<
GridAndStride
>&
grid_strides
);
void
generate_yolox_proposals
(
std
::
vector
<
GridAndStride
>
grid_strides
,
float
*
feat_blob
,
float
prob_threshold
,
std
::
vector
<
Object
>&
objects
);
void
qsort_descent_inplace
(
std
::
vector
<
Object
>&
faceobjects
,
int
left
,
int
right
);
void
qsort_descent_inplace
(
std
::
vector
<
Object
>&
objects
);
void
nms_sorted_bboxes
(
const
std
::
vector
<
Object
>&
faceobjects
,
std
::
vector
<
int
>&
picked
,
float
nms_threshold
);
inline
float
intersection_area
(
const
Object
&
a
,
const
Object
&
b
);
ErrorCode
Detect
(
const
cv
::
Mat
&
srcImage
,
std
::
vector
<
std
::
size_t
>
&
relInputShape
,
std
::
vector
<
ResultOfDetection
>
&
resultsOfDetection
,
bool
dynamic
);
ErrorCode
Initialize
(
InitializationParameterOfDetector
initializationParameterOfDetector
);
ErrorCode
Detect
(
const
cv
::
Mat
&
srcImage
,
const
std
::
vector
<
std
::
size_t
>
&
relInputShape
,
std
::
vector
<
ResultOfDetection
>
&
resultsOfDetection
);
private:
void
decode_outputs
(
float
*
prob
,
std
::
vector
<
Object
>
&
objects
,
float
scalew
,
float
scaleh
,
const
int
img_w
,
const
int
img_h
,
cv
::
Size
inputSize
);
void
generate_grids_and_stride
(
std
::
vector
<
int
>
&
strides
,
std
::
vector
<
GridAndStride
>
&
grid_strides
,
cv
::
Size
inputSize
);
void
generate_yolox_proposals
(
std
::
vector
<
GridAndStride
>
grid_strides
,
float
*
feat_blob
,
float
prob_threshold
,
std
::
vector
<
Object
>
&
objects
);
void
qsort_descent_inplace
(
std
::
vector
<
Object
>
&
faceobjects
,
int
left
,
int
right
);
void
qsort_descent_inplace
(
std
::
vector
<
Object
>
&
objects
);
void
nms_sorted_bboxes
(
const
std
::
vector
<
Object
>
&
faceobjects
,
std
::
vector
<
int
>
&
picked
,
float
nms_threshold
);
inline
float
intersection_area
(
const
Object
&
a
,
const
Object
&
b
);
private:
cv
::
FileStorage
configurationFile
;
cv
::
FileStorage
configurationFile
;
migraphx
::
program
net
;
migraphx
::
program
net
;
...
@@ -57,15 +62,13 @@ private:
...
@@ -57,15 +62,13 @@ private:
std
::
string
inputName
;
std
::
string
inputName
;
std
::
string
modelPath
;
std
::
string
modelPath
;
migraphx
::
shape
inputShape
;
migraphx
::
shape
inputShape
;
bool
useFP16
;
bool
useFP16
;
std
::
vector
<
std
::
string
>
classNames
;
std
::
vector
<
std
::
string
>
classNames
;
YOLOXParameter
yoloxParameter
;
YOLOXParameter
yoloxParameter
;
};
};
}
}
// namespace migraphxSamples
#endif
#endif
Src/main.cpp
View file @
a5e2341e
#include <Filesystem.h>
#include <SimpleLog.h>
#include <YOLOX.h>
#include <stdio.h>
#include <stdio.h>
#include <stdlib.h>
#include <stdlib.h>
#include <string.h>
#include <string.h>
#include <SimpleLog.h>
#include <Filesystem.h>
#include <YOLOX.h>
void
MIGraphXSamplesUsage
(
char
*
programName
)
void
MIGraphXSamplesUsage
(
char
*
programName
)
{
{
printf
(
"Usage : %s <index>
\n
"
,
programName
);
printf
(
"Usage : %s <index>
\n
"
,
programName
);
printf
(
"index:
\n
"
);
printf
(
"index:
\n
"
);
printf
(
"
\t
0) YOLOX sample.
\n
"
);
printf
(
"
\t
0) YOLOX sample.
\n
"
);
// printf("\t 1) YOLOX Dynamic sample.\n"); 暂不支持
}
}
void
Sample_YOLOX
();
void
Sample_YOLOX
();
void
Sample_YOLOX_Dynamic
();
int
main
(
int
argc
,
char
*
argv
[])
int
main
(
int
argc
,
char
*
argv
[])
{
{
if
(
argc
<
2
||
argc
>
2
)
{
if
(
argc
<
2
||
argc
>
2
)
{
MIGraphXSamplesUsage
(
argv
[
0
]);
MIGraphXSamplesUsage
(
argv
[
0
]);
return
-
1
;
return
-
1
;
}
}
if
(
!
strncmp
(
argv
[
1
],
"-h"
,
2
))
if
(
!
strncmp
(
argv
[
1
],
"-h"
,
2
))
{
{
MIGraphXSamplesUsage
(
argv
[
0
]);
MIGraphXSamplesUsage
(
argv
[
0
]);
return
0
;
return
0
;
}
}
switch
(
*
argv
[
1
])
switch
(
*
argv
[
1
])
{
{
case
'0'
:
{
case
'0'
:
Sample_YOLOX
();
{
break
;
Sample_YOLOX
();
}
break
;
case
'1'
:
{
}
break
;
case
'1'
:
}
{
default:
{
// Sample_YOLOX_Dynamic(); 暂不支持
MIGraphXSamplesUsage
(
argv
[
0
]);
break
;
break
;
}
}
default
:
{
MIGraphXSamplesUsage
(
argv
[
0
]);
break
;
}
}
}
return
0
;
return
0
;
}
}
void
Sample_YOLOX
()
void
Sample_YOLOX
()
{
{
// 创建YOLOX检测器
// 创建YOLOX检测器
migraphxSamples
::
DetectorYOLOX
detector
;
migraphxSamples
::
DetectorYOLOX
detector
;
migraphxSamples
::
InitializationParameterOfDetector
initParamOfDetectorYOLOX
;
migraphxSamples
::
InitializationParameterOfDetector
initParamOfDetectorYOLOX
;
initParamOfDetectorYOLOX
.
configFilePath
=
CONFIG_FILE
;
initParamOfDetectorYOLOX
.
configFilePath
=
CONFIG_FILE
;
migraphxSamples
::
ErrorCode
errorCode
=
detector
.
Initialize
(
initParamOfDetectorYOLOX
,
false
);
migraphxSamples
::
ErrorCode
errorCode
=
if
(
errorCode
!=
migraphxSamples
::
SUCCESS
)
detector
.
Initialize
(
initParamOfDetectorYOLOX
,
false
);
{
if
(
errorCode
!=
migraphxSamples
::
SUCCESS
)
{
LOG_ERROR
(
stdout
,
"fail to initialize detector!
\n
"
);
LOG_ERROR
(
stdout
,
"fail to initialize detector!
\n
"
);
exit
(
-
1
);
exit
(
-
1
);
}
}
LOG_INFO
(
stdout
,
"succeed to initialize detector
\n
"
);
LOG_INFO
(
stdout
,
"succeed to initialize detector
\n
"
);
// 读取测试图片
// 读取测试图片
cv
::
Mat
srcImage
=
cv
::
imread
(
"../Resource/Images/image_test.jpg"
,
1
);
cv
::
Mat
srcImage
=
cv
::
imread
(
"../Resource/Images/image_test.jpg"
,
1
);
// 静态推理固定尺寸
// 静态推理固定尺寸
std
::
vector
<
std
::
size_t
>
inputShape
=
{
1
,
3
,
640
,
640
};
std
::
vector
<
std
::
size_t
>
inputShape
=
{
1
,
3
,
640
,
640
};
// 推理
// 推理
std
::
vector
<
migraphxSamples
::
ResultOfDetection
>
predictions
;
std
::
vector
<
migraphxSamples
::
ResultOfDetection
>
predictions
;
double
time1
=
cv
::
getTickCount
();
double
time1
=
cv
::
getTickCount
();
detector
.
Detect
(
srcImage
,
inputShape
,
predictions
,
false
);
detector
.
Detect
(
srcImage
,
inputShape
,
predictions
,
false
);
double
time2
=
cv
::
getTickCount
();
double
time2
=
cv
::
getTickCount
();
double
elapsedTime
=
(
time2
-
time1
)
*
1000
/
cv
::
getTickFrequency
();
double
elapsedTime
=
(
time2
-
time1
)
*
1000
/
cv
::
getTickFrequency
();
LOG_INFO
(
stdout
,
"inference time:%f ms
\n
"
,
elapsedTime
);
LOG_INFO
(
stdout
,
"inference time:%f ms
\n
"
,
elapsedTime
);
// 获取推理结果
// 获取推理结果
LOG_INFO
(
stdout
,
"========== Detection Results ==========
\n
"
);
LOG_INFO
(
stdout
,
"========== Detection Results ==========
\n
"
);
for
(
int
i
=
0
;
i
<
predictions
.
size
();
++
i
)
for
(
int
i
=
0
;
i
<
predictions
.
size
();
++
i
)
{
{
migraphxSamples
::
ResultOfDetection
result
=
predictions
[
i
];
migraphxSamples
::
ResultOfDetection
result
=
predictions
[
i
];
cv
::
rectangle
(
srcImage
,
result
.
boundingBox
,
cv
::
Scalar
(
0
,
255
,
255
),
2
);
cv
::
rectangle
(
srcImage
,
result
.
boundingBox
,
cv
::
Scalar
(
0
,
255
,
255
),
2
);
std
::
string
label
=
cv
::
format
(
"%.2f"
,
result
.
confidence
);
std
::
string
label
=
cv
::
format
(
"%.2f"
,
result
.
confidence
);
label
=
result
.
className
+
" "
+
label
;
label
=
result
.
className
+
" "
+
label
;
int
left
=
predictions
[
i
].
boundingBox
.
x
;
int
left
=
predictions
[
i
].
boundingBox
.
x
;
int
top
=
predictions
[
i
].
boundingBox
.
y
;
int
top
=
predictions
[
i
].
boundingBox
.
y
;
int
baseLine
;
int
baseLine
;
cv
::
Size
labelSize
=
cv
::
getTextSize
(
label
,
cv
::
FONT_HERSHEY_SIMPLEX
,
0.5
,
1
,
&
baseLine
);
cv
::
Size
labelSize
=
cv
::
getTextSize
(
label
,
cv
::
FONT_HERSHEY_SIMPLEX
,
0.5
,
1
,
&
baseLine
);
top
=
max
(
top
,
labelSize
.
height
);
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
);
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
);
LOG_INFO
(
stdout
,
"box:%d %d %d %d,label:%d,confidence:%f
\n
"
,
}
predictions
[
i
].
boundingBox
.
x
,
predictions
[
i
].
boundingBox
.
y
,
cv
::
imwrite
(
"Result.jpg"
,
srcImage
);
predictions
[
i
].
boundingBox
.
width
,
LOG_INFO
(
stdout
,
"Detection results have been saved to ./Result.jpg
\n
"
);
predictions
[
i
].
boundingBox
.
height
,
predictions
[
i
].
classID
,
predictions
[
i
].
confidence
);
}
void
Sample_YOLOX_Dynamic
()
{
// 创建YOLOX检测器
migraphxSamples
::
DetectorYOLOX
detector
;
migraphxSamples
::
InitializationParameterOfDetector
initParamOfDetectorYOLOX
;
initParamOfDetectorYOLOX
.
configFilePath
=
CONFIG_FILE
;
migraphxSamples
::
ErrorCode
errorCode
=
detector
.
Initialize
(
initParamOfDetectorYOLOX
,
true
);
if
(
errorCode
!=
migraphxSamples
::
SUCCESS
)
{
LOG_ERROR
(
stdout
,
"fail to initialize detector!
\n
"
);
exit
(
-
1
);
}
LOG_INFO
(
stdout
,
"succeed to initialize detector
\n
"
);
// 读取测试图像
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
)
{
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
,
true
);
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
"
);
}
}
\ 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