Feng Wang
commited on
Commit
·
d8de31e
1
Parent(s):
b52aedd
fix(demo): update yolox.cpp in ncnn (#402)
Browse files- demo/ncnn/cpp/README.md +2 -1
- demo/ncnn/cpp/yolox.cpp +27 -23
demo/ncnn/cpp/README.md
CHANGED
@@ -1,6 +1,7 @@
|
|
1 |
# YOLOX-CPP-ncnn
|
2 |
|
3 |
-
Cpp file compile of YOLOX object detection base on [ncnn](https://github.com/Tencent/ncnn).
|
|
|
4 |
|
5 |
## Tutorial
|
6 |
|
|
|
1 |
# YOLOX-CPP-ncnn
|
2 |
|
3 |
+
Cpp file compile of YOLOX object detection base on [ncnn](https://github.com/Tencent/ncnn).
|
4 |
+
YOLOX is included in ncnn now, you could also try building from ncnn, it's better.
|
5 |
|
6 |
## Tutorial
|
7 |
|
demo/ncnn/cpp/yolox.cpp
CHANGED
@@ -27,6 +27,10 @@
|
|
27 |
#include <stdio.h>
|
28 |
#include <vector>
|
29 |
|
|
|
|
|
|
|
|
|
30 |
// YOLOX use the same focus in yolov5
|
31 |
class YoloV5Focus : public ncnn::Layer
|
32 |
{
|
@@ -177,14 +181,19 @@ static void nms_sorted_bboxes(const std::vector<Object>& faceobjects, std::vecto
|
|
177 |
|
178 |
static void generate_grids_and_stride(const int target_size, std::vector<int>& strides, std::vector<GridAndStride>& grid_strides)
|
179 |
{
|
180 |
-
for (
|
181 |
{
|
|
|
182 |
int num_grid = target_size / stride;
|
183 |
for (int g1 = 0; g1 < num_grid; g1++)
|
184 |
{
|
185 |
for (int g0 = 0; g0 < num_grid; g0++)
|
186 |
{
|
187 |
-
|
|
|
|
|
|
|
|
|
188 |
}
|
189 |
}
|
190 |
}
|
@@ -193,10 +202,7 @@ static void generate_grids_and_stride(const int target_size, std::vector<int>& s
|
|
193 |
static void generate_yolox_proposals(std::vector<GridAndStride> grid_strides, const ncnn::Mat& feat_blob, float prob_threshold, std::vector<Object>& objects)
|
194 |
{
|
195 |
const int num_grid = feat_blob.h;
|
196 |
-
fprintf(stderr, "output height: %d, width: %d, channels: %d, dims:%d\n", feat_blob.h, feat_blob.w, feat_blob.c, feat_blob.dims);
|
197 |
-
|
198 |
const int num_class = feat_blob.w - 5;
|
199 |
-
|
200 |
const int num_anchors = grid_strides.size();
|
201 |
|
202 |
const float* feat_ptr = feat_blob.channel(0);
|
@@ -239,7 +245,7 @@ static void generate_yolox_proposals(std::vector<GridAndStride> grid_strides, co
|
|
239 |
|
240 |
} // point anchor loop
|
241 |
}
|
242 |
-
|
243 |
static int detect_yolox(const cv::Mat& bgr, std::vector<Object>& objects)
|
244 |
{
|
245 |
ncnn::Net yolox;
|
@@ -247,17 +253,14 @@ static int detect_yolox(const cv::Mat& bgr, std::vector<Object>& objects)
|
|
247 |
yolox.opt.use_vulkan_compute = true;
|
248 |
// yolox.opt.use_bf16_storage = true;
|
249 |
|
|
|
250 |
yolox.register_custom_layer("YoloV5Focus", YoloV5Focus_layer_creator);
|
251 |
|
252 |
-
// original pretrained model from https://github.com/
|
253 |
-
//
|
254 |
yolox.load_param("yolox.param");
|
255 |
yolox.load_model("yolox.bin");
|
256 |
|
257 |
-
const int target_size = 416;
|
258 |
-
const float prob_threshold = 0.3f;
|
259 |
-
const float nms_threshold = 0.65f;
|
260 |
-
|
261 |
int img_w = bgr.cols;
|
262 |
int img_h = bgr.rows;
|
263 |
|
@@ -266,21 +269,21 @@ static int detect_yolox(const cv::Mat& bgr, std::vector<Object>& objects)
|
|
266 |
float scale = 1.f;
|
267 |
if (w > h)
|
268 |
{
|
269 |
-
scale = (float)
|
270 |
-
w =
|
271 |
h = h * scale;
|
272 |
}
|
273 |
else
|
274 |
{
|
275 |
-
scale = (float)
|
276 |
-
h =
|
277 |
w = w * scale;
|
278 |
}
|
279 |
ncnn::Mat in = ncnn::Mat::from_pixels_resize(bgr.data, ncnn::Mat::PIXEL_BGR2RGB, img_w, img_h, w, h);
|
280 |
|
281 |
-
// pad to
|
282 |
-
int wpad =
|
283 |
-
int hpad =
|
284 |
ncnn::Mat in_pad;
|
285 |
// different from yolov5, yolox only pad on bottom and right side,
|
286 |
// which means users don't need to extra padding info to decode boxes coordinate.
|
@@ -303,10 +306,11 @@ static int detect_yolox(const cv::Mat& bgr, std::vector<Object>& objects)
|
|
303 |
ncnn::Mat out;
|
304 |
ex.extract("output", out);
|
305 |
|
306 |
-
|
|
|
307 |
std::vector<GridAndStride> grid_strides;
|
308 |
-
generate_grids_and_stride(
|
309 |
-
generate_yolox_proposals(grid_strides, out,
|
310 |
}
|
311 |
|
312 |
// sort all proposals by score from highest to lowest
|
@@ -314,7 +318,7 @@ static int detect_yolox(const cv::Mat& bgr, std::vector<Object>& objects)
|
|
314 |
|
315 |
// apply nms with nms_threshold
|
316 |
std::vector<int> picked;
|
317 |
-
nms_sorted_bboxes(proposals, picked,
|
318 |
|
319 |
int count = picked.size();
|
320 |
|
|
|
27 |
#include <stdio.h>
|
28 |
#include <vector>
|
29 |
|
30 |
+
#define YOLOX_NMS_THRESH 0.45 // nms threshold
|
31 |
+
#define YOLOX_CONF_THRESH 0.25 // threshold of bounding box prob
|
32 |
+
#define YOLOX_TARGET_SIZE 640 // target image size after resize, might use 416 for small model
|
33 |
+
|
34 |
// YOLOX use the same focus in yolov5
|
35 |
class YoloV5Focus : public ncnn::Layer
|
36 |
{
|
|
|
181 |
|
182 |
static void generate_grids_and_stride(const int target_size, std::vector<int>& strides, std::vector<GridAndStride>& grid_strides)
|
183 |
{
|
184 |
+
for (int i = 0; i < (int)strides.size(); i++)
|
185 |
{
|
186 |
+
int stride = strides[i];
|
187 |
int num_grid = target_size / stride;
|
188 |
for (int g1 = 0; g1 < num_grid; g1++)
|
189 |
{
|
190 |
for (int g0 = 0; g0 < num_grid; g0++)
|
191 |
{
|
192 |
+
GridAndStride gs;
|
193 |
+
gs.grid0 = g0;
|
194 |
+
gs.grid1 = g1;
|
195 |
+
gs.stride = stride;
|
196 |
+
grid_strides.push_back(gs);
|
197 |
}
|
198 |
}
|
199 |
}
|
|
|
202 |
static void generate_yolox_proposals(std::vector<GridAndStride> grid_strides, const ncnn::Mat& feat_blob, float prob_threshold, std::vector<Object>& objects)
|
203 |
{
|
204 |
const int num_grid = feat_blob.h;
|
|
|
|
|
205 |
const int num_class = feat_blob.w - 5;
|
|
|
206 |
const int num_anchors = grid_strides.size();
|
207 |
|
208 |
const float* feat_ptr = feat_blob.channel(0);
|
|
|
245 |
|
246 |
} // point anchor loop
|
247 |
}
|
248 |
+
|
249 |
static int detect_yolox(const cv::Mat& bgr, std::vector<Object>& objects)
|
250 |
{
|
251 |
ncnn::Net yolox;
|
|
|
253 |
yolox.opt.use_vulkan_compute = true;
|
254 |
// yolox.opt.use_bf16_storage = true;
|
255 |
|
256 |
+
// Focus in yolov5
|
257 |
yolox.register_custom_layer("YoloV5Focus", YoloV5Focus_layer_creator);
|
258 |
|
259 |
+
// original pretrained model from https://github.com/Megvii-BaseDetection/YOLOX
|
260 |
+
// ncnn model param: https://github.com/Megvii-BaseDetection/storage/releases/download/0.0.1/yolox_s_ncnn.tar.gz
|
261 |
yolox.load_param("yolox.param");
|
262 |
yolox.load_model("yolox.bin");
|
263 |
|
|
|
|
|
|
|
|
|
264 |
int img_w = bgr.cols;
|
265 |
int img_h = bgr.rows;
|
266 |
|
|
|
269 |
float scale = 1.f;
|
270 |
if (w > h)
|
271 |
{
|
272 |
+
scale = (float)YOLOX_TARGET_SIZE / w;
|
273 |
+
w = YOLOX_TARGET_SIZE;
|
274 |
h = h * scale;
|
275 |
}
|
276 |
else
|
277 |
{
|
278 |
+
scale = (float)YOLOX_TARGET_SIZE / h;
|
279 |
+
h = YOLOX_TARGET_SIZE;
|
280 |
w = w * scale;
|
281 |
}
|
282 |
ncnn::Mat in = ncnn::Mat::from_pixels_resize(bgr.data, ncnn::Mat::PIXEL_BGR2RGB, img_w, img_h, w, h);
|
283 |
|
284 |
+
// pad to YOLOX_TARGET_SIZE rectangle
|
285 |
+
int wpad = YOLOX_TARGET_SIZE - w;
|
286 |
+
int hpad = YOLOX_TARGET_SIZE - h;
|
287 |
ncnn::Mat in_pad;
|
288 |
// different from yolov5, yolox only pad on bottom and right side,
|
289 |
// which means users don't need to extra padding info to decode boxes coordinate.
|
|
|
306 |
ncnn::Mat out;
|
307 |
ex.extract("output", out);
|
308 |
|
309 |
+
static const int stride_arr[] = {8, 16, 32}; // might have stride=64 in YOLOX
|
310 |
+
std::vector<int> strides(stride_arr, stride_arr + sizeof(stride_arr) / sizeof(stride_arr[0]));
|
311 |
std::vector<GridAndStride> grid_strides;
|
312 |
+
generate_grids_and_stride(YOLOX_TARGET_SIZE, strides, grid_strides);
|
313 |
+
generate_yolox_proposals(grid_strides, out, YOLOX_CONF_THRESH, proposals);
|
314 |
}
|
315 |
|
316 |
// sort all proposals by score from highest to lowest
|
|
|
318 |
|
319 |
// apply nms with nms_threshold
|
320 |
std::vector<int> picked;
|
321 |
+
nms_sorted_bboxes(proposals, picked, YOLOX_NMS_THRESH);
|
322 |
|
323 |
int count = picked.size();
|
324 |
|