Feng Wang commited on
Commit
d8de31e
·
1 Parent(s): b52aedd

fix(demo): update yolox.cpp in ncnn (#402)

Browse files
Files changed (2) hide show
  1. demo/ncnn/cpp/README.md +2 -1
  2. 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 (auto stride : strides)
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
- grid_strides.push_back((GridAndStride){g0, g1, stride});
 
 
 
 
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/yolox
253
- // TODO ncnn model https://github.com/nihui/ncnn-assets/tree/master/models
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)target_size / w;
270
- w = target_size;
271
  h = h * scale;
272
  }
273
  else
274
  {
275
- scale = (float)target_size / h;
276
- h = target_size;
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 target_size rectangle
282
- int wpad = target_size - w;
283
- int hpad = target_size - h;
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
- std::vector<int> strides = {8, 16, 32}; // might have stride=64
 
307
  std::vector<GridAndStride> grid_strides;
308
- generate_grids_and_stride(target_size, strides, grid_strides);
309
- generate_yolox_proposals(grid_strides, out, prob_threshold, proposals);
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, nms_threshold);
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