├── .gitignore ├── Demo_Detection.cpp ├── FasterRCNN.cpp ├── FasterRCNN.h ├── README.md ├── build.sh ├── config.h ├── detection_test.ncnnproto ├── ncnn_include ├── blob.h ├── cpu.h ├── layer.h ├── layer_declaration.h ├── layer_registry.h ├── mat.h ├── net.h └── platform.h ├── nms.h ├── proposal_test.ncnnproto └── win ├── layer_declaration.h ├── layer_registry.h └── platform.h /.gitignore: -------------------------------------------------------------------------------- 1 | # Prerequisites 2 | *.d 3 | 4 | # Compiled Object files 5 | *.slo 6 | *.lo 7 | *.o 8 | *.obj 9 | 10 | # Precompiled Headers 11 | *.gch 12 | *.pch 13 | 14 | # Compiled Dynamic libraries 15 | *.so 16 | *.dylib 17 | *.dll 18 | 19 | # Fortran module files 20 | *.mod 21 | *.smod 22 | 23 | # Compiled Static libraries 24 | *.lai 25 | *.la 26 | *.a 27 | *.lib 28 | 29 | # Executables 30 | *.exe 31 | *.out 32 | *.app 33 | -------------------------------------------------------------------------------- /Demo_Detection.cpp: -------------------------------------------------------------------------------- 1 | #include "FasterRCNN.h" 2 | #include 3 | 4 | void vis_boxes(cv::Mat &image, int num_out, 5 | float* boxes, float* scores, float CONF_THRESH) { 6 | const int BOX_DIMS = 4; 7 | for (int i = 0; i < num_out; i++) { 8 | 9 | if (scores[i] > CONF_THRESH) { 10 | cv::rectangle(image, 11 | cv::Point(boxes[i * BOX_DIMS + 0], 12 | boxes[i * BOX_DIMS + 1]), 13 | cv::Point(boxes[i * BOX_DIMS + 2], 14 | boxes[i * BOX_DIMS + 3]), 15 | cv::Scalar(255, 0, 0)); 16 | char text[32]; 17 | sprintf(text, "%.3f", scores[i]); 18 | cv::putText(image, text, 19 | cv::Point(boxes[i * BOX_DIMS + 0], 20 | boxes[i * BOX_DIMS + 1]), 21 | CV_FONT_HERSHEY_DUPLEX, 1.0f, cv::Scalar(255, 0, 0)); 22 | } 23 | } 24 | } 25 | 26 | void setPixel(float* bytes, int width, int height, float value, int w, int h, int c) { 27 | 28 | bytes[c*(width*height) + h*width + w] = value; 29 | } 30 | 31 | // void cvMat2bytes(cv::Mat m, float* bytes){ 32 | 33 | // #pragma omp parallel for collapse(2) 34 | // for (int h = 0; h < m.rows; ++h) { 35 | // for (int w = 0; w < m.cols; ++w) { 36 | // bytes[(0 * m.rows + h) * m.cols + w] = float( 37 | // m.at(cv::Point(w, h))[0]); 38 | // bytes[(1 * m.rows + h) * m.cols + w] = float( 39 | // m.at(cv::Point(w, h))[1]); 40 | // bytes[(2 * m.rows + h) * m.cols + w] = float( 41 | // m.at(cv::Point(w, h))[2]); 42 | // } 43 | // } 44 | // } 45 | 46 | void cvMat2bytes(cv::Mat m, float* bytes){ 47 | 48 | #pragma omp parallel for collapse(2) 49 | for (int h = 0; h < m.rows; ++h) { 50 | for (int w = 0; w < m.cols; ++w) { 51 | bytes[(0 * m.rows + h) * m.cols + w] = (float)(m.data[h*(3*m.cols)+w*3+0]); 52 | bytes[(1 * m.rows + h) * m.cols + w] = (float)(m.data[h*(3*m.cols)+w*3+1]); 53 | bytes[(2 * m.rows + h) * m.cols + w] = (float)(m.data[h*(3*m.cols)+w*3+2]); 54 | } 55 | } 56 | } 57 | 58 | int main() 59 | { 60 | const char * model_file = "./model/proposal_test.ncnnproto"; 61 | const char * weights_file = "./model/proposal_final.ncnnbin"; 62 | const char * detection_model_file = "./model/detection_test.ncnnproto"; 63 | const char * detection_weights_file = "./model/detection_final.ncnnbin"; 64 | 65 | FasterRCNN faster_rcnn; 66 | printf("init rpn net\n"); 67 | faster_rcnn.initRPN_NET(model_file, weights_file); 68 | printf("init fast net\n"); 69 | faster_rcnn.initFastRCNN_NET(detection_model_file, detection_weights_file); 70 | printf("start\n"); 71 | const char * images[] = { "./we.png"}; 72 | int width = 1000; 73 | int height = 595; 74 | for (int i = 0;i<1;i++){ 75 | cv::Mat src = cv::imread(images[i],3); 76 | cv::Mat dst; 77 | cv::resize(src, dst, cv::Size(width, height)); 78 | float* bytes = new float[width*height*3]; 79 | cvMat2bytes(dst, bytes); 80 | faster_rcnn.proposal_im_detect(bytes, width, height, 3); 81 | printf("per\n"); 82 | faster_rcnn.fast_rcnn_conv_feat_detect(); 83 | printf("fast\n"); 84 | vis_boxes(dst, faster_rcnn.getDetectionNum(), faster_rcnn.getDetectionBoxes(), faster_rcnn.getDetectionScores(), 0.90); 85 | printf("show\n"); 86 | faster_rcnn.release(); 87 | cv::imwrite("faster-rcnn.jpg",dst); 88 | cv::imshow("faster-rcnn",dst); 89 | cv::waitKey(0); 90 | delete[] bytes; 91 | } 92 | return 0; 93 | } -------------------------------------------------------------------------------- /FasterRCNN.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include "FasterRCNN.h" 4 | 5 | FasterRCNN::FasterRCNN() { 6 | 7 | proposal_boxes = NULL; 8 | proposal_scores = NULL; 9 | detection_boxes = NULL; 10 | detection_scores = NULL; 11 | } 12 | 13 | FasterRCNN::~FasterRCNN() { 14 | this->release(); 15 | } 16 | 17 | void FasterRCNN::release() { 18 | 19 | if (proposal_boxes != NULL) { 20 | 21 | delete[] proposal_boxes; 22 | proposal_boxes = NULL; 23 | } 24 | 25 | if (proposal_scores != NULL) { 26 | 27 | delete[] proposal_scores; 28 | proposal_scores = NULL; 29 | } 30 | 31 | if (detection_boxes != NULL) { 32 | 33 | delete[] detection_boxes; 34 | detection_boxes = NULL; 35 | } 36 | 37 | if (detection_scores != NULL) { 38 | 39 | delete[] detection_scores; 40 | detection_scores = NULL; 41 | } 42 | 43 | } 44 | 45 | void FasterRCNN::initRPN_NET(const char* model_file, 46 | const char* weights_file) { 47 | 48 | rpn_net.load_param(model_file); 49 | if (weights_file) 50 | rpn_net.load_model(weights_file); 51 | } 52 | 53 | void FasterRCNN::initFastRCNN_NET(const char* model_file, 54 | const char* weights_file) { 55 | 56 | fast_rcnn_net.load_param(model_file); 57 | if (weights_file) 58 | fast_rcnn_net.load_model(weights_file); 59 | } 60 | 61 | void bytes2ncnnMat(ncnn::Mat &m, float* bytes){ 62 | 63 | #pragma omp parallel for 64 | for(int i =0;i 0) 201 | top_num = std::min(valid_num, cfg.per_nms_topN); 202 | 203 | nms(pred_boxes, pred_scores, top_num, cfg.nms_overlap_thresint, 204 | pick_num, boxes_nms, scores_nms); 205 | 206 | 207 | if (cfg.after_nms_topN > 0) 208 | proposal_num = std::min(pick_num, cfg.after_nms_topN); 209 | 210 | proposal_boxes = new float[proposal_num * BOX_DIMS]; 211 | proposal_scores = new float[proposal_num]; 212 | #pragma omp parallel for 213 | for (int i = 0; i < proposal_num; i++) { 214 | 215 | proposal_boxes[i * BOX_DIMS + 0] = boxes_nms[i * BOX_DIMS + 0]; 216 | proposal_boxes[i * BOX_DIMS + 1] = boxes_nms[i * BOX_DIMS + 1]; 217 | proposal_boxes[i * BOX_DIMS + 2] = boxes_nms[i * BOX_DIMS + 2]; 218 | proposal_boxes[i * BOX_DIMS + 3] = boxes_nms[i * BOX_DIMS + 3]; 219 | proposal_scores[i] = scores_nms[i]; 220 | } 221 | // FILE* fp = fopen("./proposal_boxes.bin","wb"); 222 | // fwrite(proposal_boxes, sizeof(float)*BOX_DIMS, proposal_num, fp); 223 | // fclose(fp); 224 | 225 | // FILE* fp2 = fopen("./conv_feat_blob_mat.bin","wb"); 226 | // fwrite(conv_feat_blob_mat.data, sizeof(float)*conv_feat_blob_mat.total(), 1, fp2); 227 | // fclose(fp2); 228 | // printf("conv_feat_blob_mat: c=%d,h=%d,w=%d\n",conv_feat_blob_mat.c,conv_feat_blob_mat.h,conv_feat_blob_mat.w); 229 | 230 | delete[] proposal_bbox_pred_data; 231 | delete[] proposal_cls_prob_data; 232 | delete[] temp; 233 | delete[] boxes_nms; 234 | delete[] scores_nms; 235 | delete[] pred_scores; 236 | delete[] pred_boxes; 237 | delete[] anchors; 238 | delete[] box_deltas; 239 | delete[] data_buf; 240 | } 241 | 242 | 243 | void FasterRCNN::fast_rcnn_conv_feat_detect() { 244 | 245 | const int BOX_DIMS = 4; 246 | 247 | float* pred_boxes = NULL; 248 | float* pred_scores = NULL; 249 | 250 | // proposal_num = 300; 251 | // proposal_boxes = new float[proposal_num*BOX_DIMS]; 252 | // FILE* fp = fopen("./proposal_boxes.bin","rb"); 253 | // fread(proposal_boxes, sizeof(float)*BOX_DIMS, proposal_num, fp); 254 | // fclose(fp); 255 | 256 | // ncnn::Mat tmat(63,38,512); 257 | // FILE* fp2 = fopen("./conv_feat_blob_mat.bin","rb"); 258 | // fread(tmat.data, sizeof(float)*tmat.total(), 1, fp2); 259 | // fclose(fp2); 260 | 261 | // conv_feat_blob_mat = tmat; 262 | 263 | //for layer data 264 | printf("c=%d,h=%d,w=%d\n",conv_feat_blob_mat.c,conv_feat_blob_mat.h,conv_feat_blob_mat.w); 265 | //for layer rois 266 | float* bbox_pred_mat_vector = new float[proposal_num*cfg.bbox_pred_num_output]; 267 | float* cls_prob_mat_vector = new float[proposal_num*cfg.cls_score_num_output]; 268 | 269 | #pragma omp parallel for 270 | for (int i = 0; i < proposal_num; i++) { 271 | 272 | ncnn::Mat roi_blob(4,1,1); 273 | float* roi_ptr = roi_blob.data; 274 | roi_ptr[3] = proposal_boxes[i * BOX_DIMS + 3] - proposal_boxes[i * BOX_DIMS + 1]; 275 | roi_ptr[2] = proposal_boxes[i * BOX_DIMS + 2] - proposal_boxes[i * BOX_DIMS + 0]; 276 | roi_ptr[1] = proposal_boxes[i * BOX_DIMS + 1]; 277 | roi_ptr[0] = proposal_boxes[i * BOX_DIMS + 0]; 278 | 279 | ncnn::Extractor ex = fast_rcnn_net.create_extractor(); 280 | ex.set_light_mode(false); 281 | ex.input(cfg.data_layer, conv_feat_blob_mat); 282 | ex.input(cfg.rois_layer, roi_blob); 283 | //for output 284 | 285 | ncnn::Mat bbox_pred_mat; 286 | ex.extract(cfg.detection_bbox_layer, bbox_pred_mat); 287 | assert(bbox_pred_mat.c == cfg.bbox_pred_num_output); 288 | assert(bbox_pred_mat.w == 1); 289 | assert(bbox_pred_mat.h == 1); 290 | 291 | int copyStart = i*cfg.bbox_pred_num_output; 292 | ncnnMat2bytes(bbox_pred_mat, bbox_pred_mat_vector+copyStart); 293 | 294 | ncnn::Mat cls_prob_mat; 295 | ex.extract(cfg.detection_cls_layer, cls_prob_mat); 296 | assert(cls_prob_mat.c == cfg.cls_score_num_output); 297 | assert(cls_prob_mat.w == 1); 298 | assert(cls_prob_mat.h == 1); 299 | int copyStart2 = i*cfg.cls_score_num_output; 300 | ncnnMat2bytes(cls_prob_mat, cls_prob_mat_vector+copyStart2); 301 | } 302 | 303 | const float* bbox_pred_data = bbox_pred_mat_vector; 304 | int bbox_pred_height = 1; 305 | int bbox_pred_width = 1; 306 | int bbox_pred_channels = cfg.bbox_pred_num_output; 307 | int bbox_pred_num = proposal_num; 308 | precess_bbox_pred(bbox_pred_data, bbox_pred_num, bbox_pred_channels, bbox_pred_width, bbox_pred_height, pred_boxes); 309 | 310 | const float* cls_prob_data = cls_prob_mat_vector; 311 | int cls_prob_height = 1; 312 | int cls_prob_width = 1; 313 | int cls_prob_channels = cfg.cls_score_num_output; 314 | int cls_prob_num = proposal_num; 315 | precess_cls_prob(cls_prob_data, cls_prob_num, cls_prob_channels, cls_prob_width, cls_prob_width, pred_scores); 316 | nms(pred_boxes, pred_scores, bbox_pred_num, 317 | cfg.nms_overlap_thresint2, detection_num, detection_boxes, 318 | detection_scores); 319 | delete[] bbox_pred_mat_vector; 320 | delete[] cls_prob_mat_vector; 321 | delete[] pred_boxes; 322 | delete[] pred_scores; 323 | 324 | } 325 | 326 | void FasterRCNN::proposal_locate_anchors(int feature_width, int feature_height, 327 | float* anchors) { 328 | 329 | const int SIZE = feature_width * feature_height; 330 | 331 | for (int c = 0; c < SIZE; c++) { 332 | 333 | for (int r = 0; r < ANCHOR_NUM; r++) { 334 | 335 | for (int n = 0; n < ANCHOR_DIM; n++) { 336 | 337 | float temp = 0; 338 | if (n % 2 == 0) { 339 | 340 | temp = (c - 1) / feature_height * cfg.feat_stride; 341 | } else { 342 | 343 | //c = 0 36 ...=0 344 | //c = 1 37 ...=16 345 | 346 | //c = 35 71...=35*16=560 347 | temp = (c % feature_height) * cfg.feat_stride; 348 | } 349 | temp += ANCHORS[r][n]; 350 | anchors[c * ANCHOR_NUM * ANCHOR_DIM + r * ANCHOR_DIM + n] = temp; 351 | } 352 | } 353 | } 354 | } 355 | 356 | void FasterRCNN::fast_rcnn_bbox_transform_inv(const float* box_deltas, 357 | float* anchors, float* pred_boxes, int num) { 358 | const int BOX_DIMS = 4; 359 | #pragma omp parallel for 360 | for (int i = 0; i < num; i++) { 361 | 362 | float src_w = anchors[i * BOX_DIMS + 2] - anchors[i * BOX_DIMS + 0] + 1; 363 | float src_h = anchors[i * BOX_DIMS + 3] - anchors[i * BOX_DIMS + 1] + 1; 364 | float src_ctr_x = float(anchors[i * BOX_DIMS + 0] + 0.5 * (src_w - 1)); 365 | float src_ctr_y = float(anchors[i * BOX_DIMS + 1] + 0.5 * (src_h - 1)); 366 | 367 | float dst_ctr_x = float(box_deltas[i * BOX_DIMS + 0]); 368 | float dst_ctr_y = float(box_deltas[i * BOX_DIMS + 1]); 369 | float dst_scl_x = float(box_deltas[i * BOX_DIMS + 2]); 370 | float dst_scl_y = float(box_deltas[i * BOX_DIMS + 3]); 371 | 372 | float pred_ctr_x = dst_ctr_x * src_w + src_ctr_x; 373 | float pred_ctr_y = dst_ctr_y * src_h + src_ctr_y; 374 | float pred_w = exp(dst_scl_x) * src_w; 375 | float pred_h = exp(dst_scl_y) * src_h; 376 | pred_boxes[i * BOX_DIMS + 0] = pred_ctr_x - 0.5 * (pred_w - 1); 377 | pred_boxes[i * BOX_DIMS + 1] = pred_ctr_y - 0.5 * (pred_h - 1); 378 | pred_boxes[i * BOX_DIMS + 2] = pred_ctr_x + 0.5 * (pred_w - 1); 379 | pred_boxes[i * BOX_DIMS + 3] = pred_ctr_y + 0.5 * (pred_h - 1); 380 | } 381 | } 382 | 383 | void FasterRCNN::clip_boxes(float* pred_boxes, int im_width, int im_height, 384 | int num) { 385 | 386 | const int BOX_DIMS = 4; 387 | #pragma omp parallel for 388 | for (int i = 0; i < num; i++) { 389 | 390 | pred_boxes[i * BOX_DIMS + 0] = std::max( 391 | std::min(pred_boxes[i * BOX_DIMS + 0], (float) im_width), 0.f); 392 | pred_boxes[i * BOX_DIMS + 1] = std::max( 393 | std::min(pred_boxes[i * BOX_DIMS + 1], (float) im_height), 0.f); 394 | pred_boxes[i * BOX_DIMS + 2] = std::max( 395 | std::min(pred_boxes[i * BOX_DIMS + 2], (float) im_width), 0.f); 396 | pred_boxes[i * BOX_DIMS + 3] = std::max( 397 | std::min(pred_boxes[i * BOX_DIMS + 3], (float) im_height), 0.f); 398 | } 399 | } 400 | 401 | void FasterRCNN::filter_boxes_sort(float* pred_boxes, float* pred_scores, 402 | int num, int &valid_num) { 403 | 404 | const int BOX_DIMS = 4; 405 | valid_num = num; 406 | for (int i = 0; i < num; i++) { 407 | 408 | int widths = pred_boxes[i * BOX_DIMS + 2] - pred_boxes[i * BOX_DIMS + 0] 409 | + 1; 410 | int heights = pred_boxes[i * BOX_DIMS + 3] 411 | - pred_boxes[i * BOX_DIMS + 1] + 1; 412 | 413 | if (widths < cfg.test_min_box_size 414 | || heights < cfg.test_min_box_size 415 | || pred_scores[i] == 0) { 416 | 417 | pred_scores[i] = 0; 418 | valid_num--; 419 | } 420 | } 421 | //sort by pred_scores 422 | for (int findMin = 0; findMin < num; findMin++) { 423 | 424 | for (int i = 0; i < num - 1 - findMin; i++) { 425 | 426 | float pro = pred_scores[i]; 427 | float next = pred_scores[i + 1]; 428 | if (pro < next) { 429 | 430 | pred_scores[i + 1] = pro; 431 | pred_scores[i] = next; 432 | 433 | //pred_boxes 434 | for (int j = 0; j < BOX_DIMS; j++) { 435 | int temp = pred_boxes[i * BOX_DIMS + j]; 436 | pred_boxes[i * BOX_DIMS + j] = pred_boxes[(i + 1) * BOX_DIMS 437 | + j]; 438 | pred_boxes[(i + 1) * BOX_DIMS + j] = temp; 439 | } 440 | } 441 | } 442 | } 443 | } 444 | 445 | void FasterRCNN::precess_bbox_pred(const float* data, int num, int channels, int width, int height, float* &pred_boxes){ 446 | 447 | float* pred_transforms = new float[num*ANCHOR_DIM];//release later 448 | pred_boxes = new float[num*ANCHOR_DIM];//for return 449 | 450 | int anchor_length = channels * width * height; 451 | assert(anchor_length == cfg.bbox_pred_num_output); 452 | #pragma omp parallel for 453 | for (int row = 0; row < num; row++) { 454 | 455 | pred_transforms[row*ANCHOR_DIM+0] = data[row * anchor_length + ANCHOR_DIM*cfg.bbox_pred_index+0]; 456 | pred_transforms[row*ANCHOR_DIM+1] = data[row * anchor_length + ANCHOR_DIM*cfg.bbox_pred_index+1]; 457 | pred_transforms[row*ANCHOR_DIM+2] = data[row * anchor_length + ANCHOR_DIM*cfg.bbox_pred_index+2]; 458 | pred_transforms[row*ANCHOR_DIM+3] = data[row * anchor_length + ANCHOR_DIM*cfg.bbox_pred_index+3]; 459 | } 460 | fast_rcnn_bbox_transform_inv(pred_transforms, proposal_boxes, 461 | pred_boxes, num); 462 | clip_boxes(pred_boxes, input_width, input_height, num); 463 | 464 | delete[] pred_transforms; 465 | } 466 | 467 | void FasterRCNN::precess_cls_prob(const float* data, int num, int channels, int width, int height, float* &pred_scores){ 468 | 469 | pred_scores = new float[num];//for return 470 | 471 | int anchor_length = channels * width * height; 472 | assert(anchor_length == cfg.cls_score_num_output); 473 | #pragma omp parallel for 474 | for (int row = 0; row < num; row++) { 475 | 476 | pred_scores[row] = data[row * anchor_length + cfg.cls_score_index]; 477 | } 478 | } 479 | 480 | 481 | void FasterRCNN::print_net(ncnn::Net net) { 482 | 483 | // cout << "************************************************" << endl; 484 | // cout << "********************" << net->name() << "**********************" 485 | // << endl; 486 | // cout << "************************************************" << endl; 487 | // vector blob_names = net->blob_names(); 488 | // for (int i = 0; i < blob_names.size(); i++) { 489 | // 490 | // int _height = net->blob_by_name(blob_names[i])->height(); 491 | // int _width = net->blob_by_name(blob_names[i])->width(); 492 | // int _channels = net->blob_by_name(blob_names[i])->channels(); 493 | // int _num = net->blob_by_name(blob_names[i])->num(); 494 | // cout << blob_names[i] << " : " << "_height = " << _height 495 | // << " _width = " << _width << " _channels = " << _channels 496 | // << " _num = " << _num << endl; 497 | // } 498 | } 499 | 500 | void FasterRCNN::log_detections(float CONF_THRESH) { 501 | const int BOX_DIMS = 4; 502 | for (int i = 0; i < detection_num; i++) { 503 | 504 | if (detection_scores[i] > CONF_THRESH) { 505 | 506 | printf("%f, %f, %f, %f, %f\n",detection_boxes[i * BOX_DIMS + 0], 507 | detection_boxes[i * BOX_DIMS + 1], 508 | detection_boxes[i * BOX_DIMS + 2], 509 | detection_boxes[i * BOX_DIMS + 3], 510 | detection_scores[i]); 511 | } 512 | } 513 | } 514 | 515 | void FasterRCNN::log_proposals(float CONF_THRESH) { 516 | const int BOX_DIMS = 4; 517 | for (int i = 0; i < proposal_num; i++) { 518 | 519 | if (proposal_scores[i] > CONF_THRESH) { 520 | 521 | printf("%f, %f, %f, %f, %f\n",proposal_boxes[i * BOX_DIMS + 0], 522 | proposal_boxes[i * BOX_DIMS + 1], 523 | proposal_boxes[i * BOX_DIMS + 2], 524 | proposal_boxes[i * BOX_DIMS + 3], 525 | proposal_scores[i]); 526 | } 527 | } 528 | } 529 | -------------------------------------------------------------------------------- /FasterRCNN.h: -------------------------------------------------------------------------------- 1 | #ifndef FASTERRCNN_H_ 2 | #define FASTERRCNN_H_ 3 | 4 | #include "ncnn_include/net.h" 5 | #include "config.h" 6 | #include "nms.h" 7 | 8 | class FasterRCNN { 9 | public: 10 | FasterRCNN(); 11 | ~FasterRCNN(); 12 | 13 | void initRPN_NET(const char* model_file, const char* weights_file); 14 | void initFastRCNN_NET(const char* model_file, const char* weights_file); 15 | 16 | void proposal_im_detect(float* bytes, int w, int h, int c); 17 | void fast_rcnn_conv_feat_detect(); 18 | 19 | static void print_net(ncnn::Net net); 20 | void log_proposals(float CONF_THRESH); 21 | void log_detections(float CONF_THRESH); 22 | 23 | float getFeatureWidth() { 24 | return feature_width_; 25 | } 26 | ; 27 | float getFeatureHeight() { 28 | return feature_height_; 29 | } 30 | ; 31 | float getDetectionNum() { 32 | return detection_num; 33 | } 34 | ; 35 | float* getDetectionBoxes() { 36 | return detection_boxes; 37 | } 38 | ; 39 | float* getDetectionScores() { 40 | return detection_scores; 41 | } 42 | ; 43 | float getProposalNum() { 44 | return proposal_num; 45 | } 46 | ; 47 | float* getProposalBoxes() { 48 | return proposal_boxes; 49 | } 50 | ; 51 | float* getProposalScores() { 52 | return proposal_scores; 53 | } 54 | ; 55 | ncnn::Net getRPN_NET() { 56 | return rpn_net; 57 | } 58 | ; 59 | ncnn::Net getFastRCNN_NET() { 60 | return fast_rcnn_net; 61 | } 62 | ; 63 | void release(); 64 | private: 65 | void proposal_locate_anchors(int feature_width, int feature_height, 66 | float* anchors); 67 | void fast_rcnn_bbox_transform_inv(const float* box_deltas, float* anchors, 68 | float* pred_boxes, int num); 69 | void clip_boxes(float* pred_boxes, int im_width, int im_height, int num); 70 | void filter_boxes_sort(float* pred_boxes, float* pred_scores, int num, 71 | int &valid_num); 72 | void precess_bbox_pred(const float* data, int num, int channels, int width, int height, float* &pred_boxes); 73 | void precess_cls_prob(const float* data, int num, int channels, int width, int height, float* &pred_scores); 74 | ncnn::Net rpn_net; 75 | ncnn::Mat conv_feat_blob_mat; 76 | ncnn::Net fast_rcnn_net; 77 | Config cfg; 78 | 79 | float scale; 80 | float input_width; 81 | float input_height; 82 | 83 | float feature_width_; 84 | float feature_height_; 85 | 86 | float *proposal_boxes; 87 | float *proposal_scores; 88 | int proposal_num; 89 | 90 | float *detection_boxes; 91 | float *detection_scores; 92 | int detection_num; 93 | }; 94 | #endif 95 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # faster-rcnn-base-on-NCNN 2 | 3 | 因为caffe的依赖库太多了,win下使用起来很繁琐,移动端部署更加麻烦。故将其caffe替换为ncnn库。 4 | ncnn:https://github.com/Tencent/ncnn 5 | 6 | linux: 7 | 下载后将src/CMakeLists.txt的82行到121行的“OFF”删掉,让所有的层都编译到库文件里面。 8 | 9 | windows: 10 | 将ncnn的源代码都添加进项目里面,并添加上本项目win下的三个文件。编译即可。 11 | PS:使用自己的模型,注意修改Config.h文件中的anchors信息等。生成新的anchors的脚本见于我的项目rfcn-caffe-cpp。 12 | 13 | 有问题欢迎邮件咨询:onlyygo@qq.com 14 | 15 | 模型可以在这里下载: 16 | https://drive.google.com/open?id=0B9OXtJAN3-R8UDZIZVRzTU4yU1E 17 | 18 | 1, delete the “OFF” in src/CMakeLists.txt from line 82 to line 121, to make all layer will be compiled in lib. 19 | 20 | 2, If you want to train model youself. You should modify the anchors setting in Config.h. The anchors can be genrate in generateanchors.py at "https://github.com/onlyygo/rfcn-caffe-cpp" 21 | 22 | 3, If you have some question, please email 'onlyygo@qq.com'. 23 | 24 | 4, model can download here 25 | 26 | https://drive.google.com/open?id=0B9OXtJAN3-R8UDZIZVRzTU4yU1E 27 | -------------------------------------------------------------------------------- /build.sh: -------------------------------------------------------------------------------- 1 | g++ -fopenmp -std=c++11 Demo_Detection.cpp FasterRCNN.cpp libncnn.a -lopencv_core -lopencv_highgui -lopencv_imgproc \ 2 | -I./ncnn_include \ 3 | -I/usr/include \ 4 | -I/usr/include/opencv \ 5 | -I/usr/include/opencv2 \ 6 | -o Demo_Detection 7 | -------------------------------------------------------------------------------- /config.h: -------------------------------------------------------------------------------- 1 | #ifndef CONFIG_H_ 2 | #define CONFIG_H_ 3 | 4 | const int ANCHOR_NUM = 9; 5 | const int ANCHOR_DIM = 4; 6 | 7 | const int ANCHORS[ANCHOR_NUM][ANCHOR_DIM] = { { -83, -39, 100, 56 }, 8 | 9 | { -175, -87, 192, 104 }, { -359, -183, 376, 200 }, { -55, -55, 72, 72 }, 10 | { -119, -119, 136, 136 }, { -247, -247, 264, 264 }, 11 | { -35, -79, 52, 96 }, { -79, -167, 96, 184 }, { -167, -343, 184, 360 } }; 12 | 13 | struct Config { 14 | 15 | int per_nms_topN = 6000; 16 | float nms_overlap_thresint = 0.7; 17 | float nms_overlap_thresint2 = 0.25; 18 | int after_nms_topN = 300; 19 | 20 | const char * data_layer = "data"; 21 | const char * rois_layer = "rois"; 22 | const char * proposal_cls_layer = "proposal_cls_prob"; 23 | const char * proposal_bbox_layer = "proposal_bbox_pred"; 24 | const char * detection_bbox_layer = "bbox_pred"; 25 | const char * detection_cls_layer = "cls_prob"; 26 | const char * shared_layer = "conv5_3_relu5_3"; 27 | int class_num = 1; 28 | int cls_score_num_output = class_num+1; 29 | int bbox_pred_num_output = (class_num+1)*ANCHOR_DIM; 30 | int cls_score_index = 1; 31 | int bbox_pred_index = 1; 32 | 33 | int feat_stride = 16; 34 | int test_min_box_size = 32; 35 | float test_max_box_radio = 1.5; 36 | float test_min_box_radio = 1.0/test_max_box_radio; 37 | }; 38 | 39 | #endif 40 | -------------------------------------------------------------------------------- /detection_test.ncnnproto: -------------------------------------------------------------------------------- 1 | 13 14 2 | Input data 0 1 data 512 50 50 3 | Input rois 0 1 rois 5 1 1 4 | ROIPooling roi_pool5 2 1 data rois pool5 7 7 0.06250000 5 | InnerProduct fc6 1 1 pool5 fc6 4096 1 102760448 6 | ReLU relu6 1 1 fc6 fc6_relu6 0.000000 7 | Dropout drop6 1 1 fc6_relu6 fc6_drop6 8 | InnerProduct fc7 1 1 fc6_drop6 fc7 4096 1 16777216 9 | ReLU relu7 1 1 fc7 fc7_relu7 0.000000 10 | Dropout drop7 1 1 fc7_relu7 fc7_drop7 11 | Split splitncnn_0 1 2 fc7_drop7 fc7_drop7_splitncnn_0 fc7_drop7_splitncnn_1 12 | InnerProduct cls_score 1 1 fc7_drop7_splitncnn_1 cls_score 2 1 8192 13 | InnerProduct bbox_pred 1 1 fc7_drop7_splitncnn_0 bbox_pred 8 1 32768 14 | Softmax cls_prob 1 1 cls_score cls_prob 15 | -------------------------------------------------------------------------------- /ncnn_include/blob.h: -------------------------------------------------------------------------------- 1 | // Tencent is pleased to support the open source community by making ncnn available. 2 | // 3 | // Copyright (C) 2017 THL A29 Limited, a Tencent company. All rights reserved. 4 | // 5 | // Licensed under the BSD 3-Clause License (the "License"); you may not use this file except 6 | // in compliance with the License. You may obtain a copy of the License at 7 | // 8 | // https://opensource.org/licenses/BSD-3-Clause 9 | // 10 | // Unless required by applicable law or agreed to in writing, software distributed 11 | // under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR 12 | // CONDITIONS OF ANY KIND, either express or implied. See the License for the 13 | // specific language governing permissions and limitations under the License. 14 | 15 | #ifndef NCNN_BLOB_H 16 | #define NCNN_BLOB_H 17 | 18 | #include 19 | #include 20 | #include "platform.h" 21 | 22 | namespace ncnn { 23 | 24 | class Blob 25 | { 26 | public: 27 | // empty 28 | Blob(); 29 | 30 | public: 31 | #if NCNN_STRING 32 | // blob name 33 | std::string name; 34 | #endif // NCNN_STRING 35 | // layer index which produce this blob as output 36 | int producer; 37 | // layer index which need this blob as input 38 | std::vector consumers; 39 | }; 40 | 41 | } // namespace ncnn 42 | 43 | #endif // NCNN_BLOB_H 44 | -------------------------------------------------------------------------------- /ncnn_include/cpu.h: -------------------------------------------------------------------------------- 1 | // Tencent is pleased to support the open source community by making ncnn available. 2 | // 3 | // Copyright (C) 2017 THL A29 Limited, a Tencent company. All rights reserved. 4 | // 5 | // Licensed under the BSD 3-Clause License (the "License"); you may not use this file except 6 | // in compliance with the License. You may obtain a copy of the License at 7 | // 8 | // https://opensource.org/licenses/BSD-3-Clause 9 | // 10 | // Unless required by applicable law or agreed to in writing, software distributed 11 | // under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR 12 | // CONDITIONS OF ANY KIND, either express or implied. See the License for the 13 | // specific language governing permissions and limitations under the License. 14 | 15 | #ifndef NCNN_CPU_H 16 | #define NCNN_CPU_H 17 | 18 | namespace ncnn { 19 | 20 | // test optional cpu features 21 | // neon = armv7 neon or aarch64 asimd 22 | int cpu_support_arm_neon(); 23 | // vfpv4 = armv7 fp16 + fma 24 | int cpu_support_arm_vfpv4(); 25 | // asimdhp = aarch64 asimd half precision 26 | int cpu_support_arm_asimdhp(); 27 | 28 | // cpu info 29 | int get_cpu_count(); 30 | 31 | // bind all threads on little clusters if powersave enabled 32 | // affacts HMP arch cpu like ARM big.LITTLE 33 | // only implemented on android at the moment 34 | // switching powersave is expensive and not thread-safe 35 | // 0 = all cores enabled(default) 36 | // 1 = only little clusters enabled 37 | // 2 = only big clusters enabled 38 | // return 0 if success for setter function 39 | int get_cpu_powersave(); 40 | int set_cpu_powersave(int powersave); 41 | 42 | // misc function wrapper for openmp routines 43 | int get_omp_num_threads(); 44 | void set_omp_num_threads(int num_threads); 45 | 46 | int get_omp_dynamic(); 47 | void set_omp_dynamic(int dynamic); 48 | 49 | } // namespace ncnn 50 | 51 | #endif // NCNN_CPU_H 52 | -------------------------------------------------------------------------------- /ncnn_include/layer.h: -------------------------------------------------------------------------------- 1 | // Tencent is pleased to support the open source community by making ncnn available. 2 | // 3 | // Copyright (C) 2017 THL A29 Limited, a Tencent company. All rights reserved. 4 | // 5 | // Licensed under the BSD 3-Clause License (the "License"); you may not use this file except 6 | // in compliance with the License. You may obtain a copy of the License at 7 | // 8 | // https://opensource.org/licenses/BSD-3-Clause 9 | // 10 | // Unless required by applicable law or agreed to in writing, software distributed 11 | // under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR 12 | // CONDITIONS OF ANY KIND, either express or implied. See the License for the 13 | // specific language governing permissions and limitations under the License. 14 | 15 | #ifndef NCNN_LAYER_H 16 | #define NCNN_LAYER_H 17 | 18 | #include 19 | #include 20 | #include 21 | #include "mat.h" 22 | #include "platform.h" 23 | 24 | namespace ncnn { 25 | 26 | class Layer 27 | { 28 | public: 29 | // empty 30 | Layer(); 31 | // virtual destructor 32 | virtual ~Layer(); 33 | 34 | #if NCNN_STDIO 35 | #if NCNN_STRING 36 | // load layer specific parameter from plain param file 37 | // return 0 if success 38 | virtual int load_param(FILE* paramfp); 39 | #endif // NCNN_STRING 40 | // load layer specific parameter from binary param file 41 | // return 0 if success 42 | virtual int load_param_bin(FILE* paramfp); 43 | 44 | // load layer specific weight data from model file 45 | // return 0 if success 46 | virtual int load_model(FILE* binfp); 47 | #endif // NCNN_STDIO 48 | 49 | // load layer specific parameter from memory 50 | // memory pointer is 32-bit aligned 51 | // return 0 if success 52 | virtual int load_param(const unsigned char*& mem); 53 | 54 | // load layer specific weight data from memory 55 | // memory pointer is 32-bit aligned 56 | // return 0 if success 57 | virtual int load_model(const unsigned char*& mem); 58 | 59 | public: 60 | // one input and one output blob 61 | bool one_blob_only; 62 | 63 | // support inplace inference 64 | bool support_inplace; 65 | 66 | public: 67 | // implement inference 68 | // return 0 if success 69 | virtual int forward(const std::vector& bottom_blobs, std::vector& top_blobs) const; 70 | virtual int forward(const Mat& bottom_blob, Mat& top_blob) const; 71 | 72 | // implement inplace inference 73 | // return 0 if success 74 | virtual int forward_inplace(std::vector& bottom_top_blobs) const; 75 | virtual int forward_inplace(Mat& bottom_top_blob) const; 76 | 77 | public: 78 | #if NCNN_STRING 79 | // layer type name 80 | std::string type; 81 | // layer name 82 | std::string name; 83 | #endif // NCNN_STRING 84 | // blob index which this layer needs as input 85 | std::vector bottoms; 86 | // blob index which this layer produces as output 87 | std::vector tops; 88 | }; 89 | 90 | namespace LayerType { 91 | enum 92 | { 93 | AbsVal = 0, 94 | ArgMax = 1, 95 | BatchNorm = 2, 96 | Bias = 3, 97 | BNLL = 4, 98 | Concat = 5, 99 | Convolution = 6, 100 | Crop = 7, 101 | Deconvolution = 8, 102 | Dropout = 9, 103 | ELU = 10, 104 | Eltwise = 11, 105 | Embed = 12, 106 | Exp = 13, 107 | Flatten = 14, 108 | InnerProduct = 15, 109 | Input = 16, 110 | Log = 17, 111 | LRN = 18, 112 | MemoryData = 19, 113 | MVN = 20, 114 | Pooling = 21, 115 | Power = 22, 116 | PReLU = 23, 117 | Proposal = 24, 118 | Reduction = 25, 119 | ReLU = 26, 120 | Reshape = 27, 121 | ROIPooling = 28, 122 | Scale = 29, 123 | Sigmoid = 30, 124 | Slice = 31, 125 | Softmax = 32, 126 | Split = 33, 127 | SPP = 34, 128 | TanH = 35, 129 | Threshold = 36, 130 | Tile = 37, 131 | RNN = 38, 132 | LSTM = 39, 133 | 134 | CustomBit = (1<<8), 135 | }; 136 | } // namespace LayerType 137 | 138 | // layer factory function 139 | typedef Layer* (*layer_creator_func)(); 140 | 141 | struct layer_registry_entry 142 | { 143 | #if NCNN_STRING 144 | // layer type name 145 | const char* name; 146 | #endif // NCNN_STRING 147 | // layer factory entry 148 | layer_creator_func creator; 149 | }; 150 | 151 | #if NCNN_STRING 152 | // get layer type from type name 153 | int layer_to_index(const char* type); 154 | #endif // NCNN_STRING 155 | // create layer from layer type 156 | Layer* create_layer(int index); 157 | 158 | #define DEFINE_LAYER_CREATOR(name) \ 159 | Layer* name##_layer_creator() { return new name; } 160 | 161 | } // namespace ncnn 162 | 163 | #endif // NCNN_LAYER_H 164 | -------------------------------------------------------------------------------- /ncnn_include/layer_declaration.h: -------------------------------------------------------------------------------- 1 | extern Layer* AbsVal_layer_creator(); 2 | extern Layer* ArgMax_layer_creator(); 3 | extern Layer* BatchNorm_layer_creator(); 4 | extern Layer* Bias_layer_creator(); 5 | extern Layer* BNLL_layer_creator(); 6 | extern Layer* Concat_layer_creator(); 7 | extern Layer* Convolution_x86_layer_creator(); 8 | extern Layer* Crop_layer_creator(); 9 | extern Layer* Deconvolution_layer_creator(); 10 | extern Layer* Dropout_layer_creator(); 11 | extern Layer* Eltwise_layer_creator(); 12 | extern Layer* ELU_layer_creator(); 13 | extern Layer* Embed_layer_creator(); 14 | extern Layer* Exp_layer_creator(); 15 | extern Layer* Flatten_layer_creator(); 16 | extern Layer* InnerProduct_layer_creator(); 17 | extern Layer* Input_layer_creator(); 18 | extern Layer* Log_layer_creator(); 19 | extern Layer* LRN_layer_creator(); 20 | extern Layer* MemoryData_layer_creator(); 21 | extern Layer* MVN_layer_creator(); 22 | extern Layer* Pooling_layer_creator(); 23 | extern Layer* Power_layer_creator(); 24 | extern Layer* PReLU_layer_creator(); 25 | extern Layer* Proposal_layer_creator(); 26 | extern Layer* Reduction_layer_creator(); 27 | extern Layer* ReLU_layer_creator(); 28 | extern Layer* Reshape_layer_creator(); 29 | extern Layer* ROIPooling_layer_creator(); 30 | extern Layer* Scale_layer_creator(); 31 | extern Layer* Sigmoid_layer_creator(); 32 | extern Layer* Slice_layer_creator(); 33 | extern Layer* Softmax_layer_creator(); 34 | extern Layer* Split_layer_creator(); 35 | extern Layer* SPP_layer_creator(); 36 | extern Layer* TanH_layer_creator(); 37 | extern Layer* Threshold_layer_creator(); 38 | extern Layer* Tile_layer_creator(); 39 | extern Layer* RNN_layer_creator(); 40 | extern Layer* LSTM_layer_creator(); 41 | -------------------------------------------------------------------------------- /ncnn_include/layer_registry.h: -------------------------------------------------------------------------------- 1 | #if NCNN_STRING 2 | {"AbsVal",AbsVal_layer_creator}, 3 | #else 4 | {AbsVal_layer_creator}, 5 | #endif 6 | #if NCNN_STRING 7 | {"ArgMax",ArgMax_layer_creator}, 8 | #else 9 | {ArgMax_layer_creator}, 10 | #endif 11 | #if NCNN_STRING 12 | {"BatchNorm",BatchNorm_layer_creator}, 13 | #else 14 | {BatchNorm_layer_creator}, 15 | #endif 16 | #if NCNN_STRING 17 | {"Bias",Bias_layer_creator}, 18 | #else 19 | {Bias_layer_creator}, 20 | #endif 21 | #if NCNN_STRING 22 | {"BNLL",BNLL_layer_creator}, 23 | #else 24 | {BNLL_layer_creator}, 25 | #endif 26 | #if NCNN_STRING 27 | {"Concat",Concat_layer_creator}, 28 | #else 29 | {Concat_layer_creator}, 30 | #endif 31 | #if NCNN_STRING 32 | {"Convolution",Convolution_x86_layer_creator}, 33 | #else 34 | {Convolution_x86_layer_creator}, 35 | #endif 36 | #if NCNN_STRING 37 | {"Crop",Crop_layer_creator}, 38 | #else 39 | {Crop_layer_creator}, 40 | #endif 41 | #if NCNN_STRING 42 | {"Deconvolution",Deconvolution_layer_creator}, 43 | #else 44 | {Deconvolution_layer_creator}, 45 | #endif 46 | #if NCNN_STRING 47 | {"Dropout",Dropout_layer_creator}, 48 | #else 49 | {Dropout_layer_creator}, 50 | #endif 51 | #if NCNN_STRING 52 | {"Eltwise",Eltwise_layer_creator}, 53 | #else 54 | {Eltwise_layer_creator}, 55 | #endif 56 | #if NCNN_STRING 57 | {"ELU",ELU_layer_creator}, 58 | #else 59 | {ELU_layer_creator}, 60 | #endif 61 | #if NCNN_STRING 62 | {"Embed",Embed_layer_creator}, 63 | #else 64 | {Embed_layer_creator}, 65 | #endif 66 | #if NCNN_STRING 67 | {"Exp",Exp_layer_creator}, 68 | #else 69 | {Exp_layer_creator}, 70 | #endif 71 | #if NCNN_STRING 72 | {"Flatten",Flatten_layer_creator}, 73 | #else 74 | {Flatten_layer_creator}, 75 | #endif 76 | #if NCNN_STRING 77 | {"InnerProduct",InnerProduct_layer_creator}, 78 | #else 79 | {InnerProduct_layer_creator}, 80 | #endif 81 | #if NCNN_STRING 82 | {"Input",Input_layer_creator}, 83 | #else 84 | {Input_layer_creator}, 85 | #endif 86 | #if NCNN_STRING 87 | {"Log",Log_layer_creator}, 88 | #else 89 | {Log_layer_creator}, 90 | #endif 91 | #if NCNN_STRING 92 | {"LRN",LRN_layer_creator}, 93 | #else 94 | {LRN_layer_creator}, 95 | #endif 96 | #if NCNN_STRING 97 | {"MemoryData",MemoryData_layer_creator}, 98 | #else 99 | {MemoryData_layer_creator}, 100 | #endif 101 | #if NCNN_STRING 102 | {"MVN",MVN_layer_creator}, 103 | #else 104 | {MVN_layer_creator}, 105 | #endif 106 | #if NCNN_STRING 107 | {"Pooling",Pooling_layer_creator}, 108 | #else 109 | {Pooling_layer_creator}, 110 | #endif 111 | #if NCNN_STRING 112 | {"Power",Power_layer_creator}, 113 | #else 114 | {Power_layer_creator}, 115 | #endif 116 | #if NCNN_STRING 117 | {"PReLU",PReLU_layer_creator}, 118 | #else 119 | {PReLU_layer_creator}, 120 | #endif 121 | #if NCNN_STRING 122 | {"Proposal",Proposal_layer_creator}, 123 | #else 124 | {Proposal_layer_creator}, 125 | #endif 126 | #if NCNN_STRING 127 | {"Reduction",Reduction_layer_creator}, 128 | #else 129 | {Reduction_layer_creator}, 130 | #endif 131 | #if NCNN_STRING 132 | {"ReLU",ReLU_layer_creator}, 133 | #else 134 | {ReLU_layer_creator}, 135 | #endif 136 | #if NCNN_STRING 137 | {"Reshape",Reshape_layer_creator}, 138 | #else 139 | {Reshape_layer_creator}, 140 | #endif 141 | #if NCNN_STRING 142 | {"ROIPooling",ROIPooling_layer_creator}, 143 | #else 144 | {ROIPooling_layer_creator}, 145 | #endif 146 | #if NCNN_STRING 147 | {"Scale",Scale_layer_creator}, 148 | #else 149 | {Scale_layer_creator}, 150 | #endif 151 | #if NCNN_STRING 152 | {"Sigmoid",Sigmoid_layer_creator}, 153 | #else 154 | {Sigmoid_layer_creator}, 155 | #endif 156 | #if NCNN_STRING 157 | {"Slice",Slice_layer_creator}, 158 | #else 159 | {Slice_layer_creator}, 160 | #endif 161 | #if NCNN_STRING 162 | {"Softmax",Softmax_layer_creator}, 163 | #else 164 | {Softmax_layer_creator}, 165 | #endif 166 | #if NCNN_STRING 167 | {"Split",Split_layer_creator}, 168 | #else 169 | {Split_layer_creator}, 170 | #endif 171 | #if NCNN_STRING 172 | {"SPP",SPP_layer_creator}, 173 | #else 174 | {SPP_layer_creator}, 175 | #endif 176 | #if NCNN_STRING 177 | {"TanH",TanH_layer_creator}, 178 | #else 179 | {TanH_layer_creator}, 180 | #endif 181 | #if NCNN_STRING 182 | {"Threshold",Threshold_layer_creator}, 183 | #else 184 | {Threshold_layer_creator}, 185 | #endif 186 | #if NCNN_STRING 187 | {"Tile",Tile_layer_creator}, 188 | #else 189 | {Tile_layer_creator}, 190 | #endif 191 | #if NCNN_STRING 192 | {"RNN",RNN_layer_creator}, 193 | #else 194 | {RNN_layer_creator}, 195 | #endif 196 | #if NCNN_STRING 197 | {"LSTM",LSTM_layer_creator}, 198 | #else 199 | {LSTM_layer_creator}, 200 | #endif 201 | -------------------------------------------------------------------------------- /ncnn_include/mat.h: -------------------------------------------------------------------------------- 1 | // Tencent is pleased to support the open source community by making ncnn available. 2 | // 3 | // Copyright (C) 2017 THL A29 Limited, a Tencent company. All rights reserved. 4 | // 5 | // Licensed under the BSD 3-Clause License (the "License"); you may not use this file except 6 | // in compliance with the License. You may obtain a copy of the License at 7 | // 8 | // https://opensource.org/licenses/BSD-3-Clause 9 | // 10 | // Unless required by applicable law or agreed to in writing, software distributed 11 | // under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR 12 | // CONDITIONS OF ANY KIND, either express or implied. See the License for the 13 | // specific language governing permissions and limitations under the License. 14 | 15 | #ifndef NCNN_MAT_H 16 | #define NCNN_MAT_H 17 | 18 | #include 19 | #include 20 | 21 | namespace ncnn { 22 | 23 | // the three dimension matrix 24 | class Mat 25 | { 26 | public: 27 | // empty 28 | Mat(); 29 | // vec 30 | Mat(int w); 31 | // image 32 | Mat(int w, int h); 33 | // dim 34 | Mat(int w, int h, int c); 35 | // copy 36 | Mat(const Mat& m); 37 | // external vec 38 | Mat(int w, float* data); 39 | // external image 40 | Mat(int w, int h, float* data); 41 | // external dim 42 | Mat(int w, int h, int c, float* data); 43 | // release 44 | ~Mat(); 45 | // assign 46 | Mat& operator=(const Mat& m); 47 | // set all 48 | void fill(float v); 49 | // deep copy 50 | Mat clone() const; 51 | // reshape vec 52 | Mat reshape(int w) const; 53 | // reshape image 54 | Mat reshape(int w, int h) const; 55 | // reshape dim 56 | Mat reshape(int w, int h, int c) const; 57 | // allocate vec 58 | void create(int w); 59 | // allocate image 60 | void create(int w, int h); 61 | // allocate dim 62 | void create(int w, int h, int c); 63 | // refcount++ 64 | void addref(); 65 | // refcount-- 66 | void release(); 67 | 68 | bool empty() const; 69 | size_t total() const; 70 | 71 | // data reference 72 | Mat channel(int c); 73 | const Mat channel(int c) const; 74 | float* row(int y); 75 | const float* row(int y) const; 76 | operator float*(); 77 | operator const float*() const; 78 | 79 | enum 80 | { 81 | PIXEL_CONVERT_SHIFT = 16, 82 | PIXEL_FORMAT_MASK = 0x0000ffff, 83 | PIXEL_CONVERT_MASK = 0xffff0000, 84 | 85 | PIXEL_RGB = 1, 86 | PIXEL_BGR = (1 << 1), 87 | PIXEL_GRAY = (1 << 2), 88 | PIXEL_RGBA = (1 << 3), 89 | 90 | PIXEL_RGB2BGR = PIXEL_RGB | (PIXEL_BGR << PIXEL_CONVERT_SHIFT), 91 | PIXEL_RGB2GRAY = PIXEL_RGB | (PIXEL_GRAY << PIXEL_CONVERT_SHIFT), 92 | 93 | PIXEL_BGR2RGB = PIXEL_BGR | (PIXEL_RGB << PIXEL_CONVERT_SHIFT), 94 | PIXEL_BGR2GRAY = PIXEL_BGR | (PIXEL_GRAY << PIXEL_CONVERT_SHIFT), 95 | 96 | PIXEL_GRAY2RGB = PIXEL_GRAY | (PIXEL_RGB << PIXEL_CONVERT_SHIFT), 97 | PIXEL_GRAY2BGR = PIXEL_GRAY | (PIXEL_BGR << PIXEL_CONVERT_SHIFT), 98 | 99 | PIXEL_RGBA2RGB = PIXEL_RGBA | (PIXEL_RGB << PIXEL_CONVERT_SHIFT), 100 | PIXEL_RGBA2BGR = PIXEL_RGBA | (PIXEL_BGR << PIXEL_CONVERT_SHIFT), 101 | PIXEL_RGBA2GRAY = PIXEL_RGBA | (PIXEL_GRAY << PIXEL_CONVERT_SHIFT), 102 | }; 103 | // convenient construct from pixel data 104 | static Mat from_pixels(const unsigned char* pixels, int type, int w, int h); 105 | // convenient construct from pixel data and resize to specific size 106 | static Mat from_pixels_resize(const unsigned char* pixels, int type, int w, int h, int target_width, int target_height); 107 | 108 | // convenient export to pixel data 109 | void to_pixels(unsigned char* pixels, int type); 110 | // convenient export to pixel data and resize to specific size 111 | void to_pixels_resize(unsigned char* pixels, int type, int target_width, int target_height); 112 | 113 | // substract channel-wise mean values, then multiply by normalize values, pass 0 to skip 114 | void substract_mean_normalize(const float* mean_vals, const float* norm_vals); 115 | 116 | // convenient construct from half precisoin floating point data 117 | static Mat from_float16(const unsigned short* data, int size); 118 | 119 | // the dimensionality 120 | int dims; 121 | // pointer to the data 122 | float* data; 123 | 124 | // pointer to the reference counter; 125 | // when points to user-allocated data, the pointer is NULL 126 | int* refcount; 127 | 128 | int w; 129 | int h; 130 | int c; 131 | 132 | size_t cstep; 133 | }; 134 | 135 | // misc function 136 | // image pixel bilinear resize 137 | void resize_bilinear_c1(const unsigned char* src, int srcw, int srch, unsigned char* dst, int w, int h); 138 | void resize_bilinear_c3(const unsigned char* src, int srcw, int srch, unsigned char* dst, int w, int h); 139 | void resize_bilinear_c4(const unsigned char* src, int srcw, int srch, unsigned char* dst, int w, int h); 140 | 141 | // mat process 142 | enum 143 | { 144 | BORDER_CONSTANT = 0, 145 | BORDER_REPLICATE = 1, 146 | }; 147 | void copy_make_border(const Mat& src, Mat& dst, int top, int bottom, int left, int right, int type, float v); 148 | void copy_cut_border(const Mat& src, Mat& dst, int top, int bottom, int left, int right); 149 | 150 | // the alignment of all the allocated buffers 151 | #define MALLOC_ALIGN 16 152 | 153 | // Aligns a pointer to the specified number of bytes 154 | // ptr Aligned pointer 155 | // n Alignment size that must be a power of two 156 | template static inline _Tp* alignPtr(_Tp* ptr, int n=(int)sizeof(_Tp)) 157 | { 158 | return (_Tp*)(((size_t)ptr + n-1) & -n); 159 | } 160 | 161 | // Aligns a buffer size to the specified number of bytes 162 | // The function returns the minimum number that is greater or equal to sz and is divisible by n 163 | // sz Buffer size to align 164 | // n Alignment size that must be a power of two 165 | static inline size_t alignSize(size_t sz, int n) 166 | { 167 | return (sz + n-1) & -n; 168 | } 169 | 170 | static inline void* fastMalloc(size_t size) 171 | { 172 | unsigned char* udata = (unsigned char*)malloc(size + sizeof(void*) + MALLOC_ALIGN); 173 | if (!udata) 174 | return 0; 175 | unsigned char** adata = alignPtr((unsigned char**)udata + 1, MALLOC_ALIGN); 176 | adata[-1] = udata; 177 | return adata; 178 | } 179 | 180 | static inline void fastFree(void* ptr) 181 | { 182 | if (ptr) 183 | { 184 | unsigned char* udata = ((unsigned char**)ptr)[-1]; 185 | free(udata); 186 | } 187 | } 188 | 189 | // exchange-add operation for atomic operations on reference counters 190 | #if defined __INTEL_COMPILER && !(defined WIN32 || defined _WIN32) 191 | // atomic increment on the linux version of the Intel(tm) compiler 192 | # define NCNN_XADD(addr, delta) (int)_InterlockedExchangeAdd(const_cast(reinterpret_cast(addr)), delta) 193 | #elif defined __GNUC__ 194 | # if defined __clang__ && __clang_major__ >= 3 && !defined __ANDROID__ && !defined __EMSCRIPTEN__ && !defined(__CUDACC__) 195 | # ifdef __ATOMIC_ACQ_REL 196 | # define NCNN_XADD(addr, delta) __c11_atomic_fetch_add((_Atomic(int)*)(addr), delta, __ATOMIC_ACQ_REL) 197 | # else 198 | # define NCNN_XADD(addr, delta) __atomic_fetch_add((_Atomic(int)*)(addr), delta, 4) 199 | # endif 200 | # else 201 | # if defined __ATOMIC_ACQ_REL && !defined __clang__ 202 | // version for gcc >= 4.7 203 | # define NCNN_XADD(addr, delta) (int)__atomic_fetch_add((unsigned*)(addr), (unsigned)(delta), __ATOMIC_ACQ_REL) 204 | # else 205 | # define NCNN_XADD(addr, delta) (int)__sync_fetch_and_add((unsigned*)(addr), (unsigned)(delta)) 206 | # endif 207 | # endif 208 | #elif defined _MSC_VER && !defined RC_INVOKED 209 | # include 210 | # define NCNN_XADD(addr, delta) (int)_InterlockedExchangeAdd((long volatile*)addr, delta) 211 | #else 212 | static inline void NCNN_XADD(int* addr, int delta) { int tmp = *addr; *addr += delta; return tmp; } 213 | #endif 214 | 215 | inline Mat::Mat() 216 | : dims(0), data(0), refcount(0), w(0), h(0), c(0), cstep(0) 217 | { 218 | } 219 | 220 | inline Mat::Mat(int _w) 221 | : dims(0), data(0), refcount(0) 222 | { 223 | create(_w); 224 | } 225 | 226 | inline Mat::Mat(int _w, int _h) 227 | : dims(0), data(0), refcount(0) 228 | { 229 | create(_w, _h); 230 | } 231 | 232 | inline Mat::Mat(int _w, int _h, int _c) 233 | : dims(0), data(0), refcount(0) 234 | { 235 | create(_w, _h, _c); 236 | } 237 | 238 | inline Mat::Mat(const Mat& m) 239 | : dims(m.dims), data(m.data), refcount(m.refcount) 240 | { 241 | if (refcount) 242 | NCNN_XADD(refcount, 1); 243 | 244 | w = m.w; 245 | h = m.h; 246 | c = m.c; 247 | 248 | cstep = m.cstep; 249 | } 250 | 251 | inline Mat::Mat(int _w, float* _data) 252 | : dims(1), data(_data), refcount(0) 253 | { 254 | w = _w; 255 | h = 1; 256 | c = 1; 257 | 258 | cstep = w; 259 | } 260 | 261 | inline Mat::Mat(int _w, int _h, float* _data) 262 | : dims(2), data(_data), refcount(0) 263 | { 264 | w = _w; 265 | h = _h; 266 | c = 1; 267 | 268 | cstep = w * h; 269 | } 270 | 271 | inline Mat::Mat(int _w, int _h, int _c, float* _data) 272 | : dims(3), data(_data), refcount(0) 273 | { 274 | w = _w; 275 | h = _h; 276 | c = _c; 277 | 278 | cstep = alignSize(w * h * sizeof(float), 16) >> 2; 279 | } 280 | 281 | inline Mat::~Mat() 282 | { 283 | release(); 284 | } 285 | 286 | inline Mat& Mat::operator=(const Mat& m) 287 | { 288 | if (this == &m) 289 | return *this; 290 | 291 | if (m.refcount) 292 | NCNN_XADD(m.refcount, 1); 293 | 294 | release(); 295 | 296 | dims = m.dims; 297 | data = m.data; 298 | refcount = m.refcount; 299 | 300 | w = m.w; 301 | h = m.h; 302 | c = m.c; 303 | 304 | cstep = m.cstep; 305 | 306 | return *this; 307 | } 308 | 309 | inline void Mat::fill(float _v) 310 | { 311 | size_t _total = total(); 312 | for (size_t i = 0; i < _total; i++) 313 | { 314 | data[i] = _v; 315 | } 316 | } 317 | 318 | inline Mat Mat::clone() const 319 | { 320 | if (empty()) 321 | return Mat(); 322 | 323 | Mat m; 324 | if (dims == 1) 325 | m.create(w); 326 | else if (dims == 2) 327 | m.create(w, h); 328 | else if (dims == 3) 329 | m.create(w, h, c); 330 | 331 | if (total() > 0) 332 | { 333 | memcpy(m.data, data, total() * sizeof(float)); 334 | } 335 | 336 | return m; 337 | } 338 | 339 | inline Mat Mat::reshape(int _w) const 340 | { 341 | Mat m = *this; 342 | 343 | m.dims = 1; 344 | 345 | m.w = _w; 346 | m.h = 1; 347 | m.c = 1; 348 | 349 | m.cstep = _w; 350 | 351 | return m; 352 | } 353 | 354 | inline Mat Mat::reshape(int _w, int _h) const 355 | { 356 | Mat m = *this; 357 | 358 | m.dims = 2; 359 | 360 | m.w = _w; 361 | m.h = _h; 362 | m.c = 1; 363 | 364 | m.cstep = _w * _h; 365 | 366 | return m; 367 | } 368 | 369 | inline Mat Mat::reshape(int _w, int _h, int _c) const 370 | { 371 | Mat m = *this; 372 | 373 | m.dims = 3; 374 | 375 | m.w = _w; 376 | m.h = _h; 377 | m.c = _c; 378 | 379 | m.cstep = alignSize(_w * _h * sizeof(float), 16) >> 2; 380 | 381 | return m; 382 | } 383 | 384 | inline void Mat::create(int _w) 385 | { 386 | release(); 387 | 388 | dims = 1; 389 | 390 | w = _w; 391 | h = 1; 392 | c = 1; 393 | 394 | cstep = w; 395 | 396 | if (total() > 0) 397 | { 398 | size_t totalsize = total() * sizeof(float); 399 | data = (float*)fastMalloc(totalsize + (int)sizeof(*refcount)); 400 | refcount = (int*)(((unsigned char*)data) + totalsize); 401 | *refcount = 1; 402 | } 403 | } 404 | 405 | inline void Mat::create(int _w, int _h) 406 | { 407 | release(); 408 | 409 | dims = 2; 410 | 411 | w = _w; 412 | h = _h; 413 | c = 1; 414 | 415 | cstep = w * h; 416 | 417 | if (total() > 0) 418 | { 419 | size_t totalsize = total() * sizeof(float); 420 | data = (float*)fastMalloc(totalsize + (int)sizeof(*refcount)); 421 | refcount = (int*)(((unsigned char*)data) + totalsize); 422 | *refcount = 1; 423 | } 424 | } 425 | 426 | inline void Mat::create(int _w, int _h, int _c) 427 | { 428 | release(); 429 | 430 | dims = 3; 431 | 432 | w = _w; 433 | h = _h; 434 | c = _c; 435 | 436 | cstep = alignSize(w * h * sizeof(float), 16) >> 2; 437 | 438 | if (total() > 0) 439 | { 440 | size_t totalsize = total() * sizeof(float); 441 | data = (float*)fastMalloc(totalsize + (int)sizeof(*refcount)); 442 | refcount = (int*)(((unsigned char*)data) + totalsize); 443 | *refcount = 1; 444 | } 445 | } 446 | 447 | inline void Mat::addref() 448 | { 449 | if (refcount) 450 | NCNN_XADD(refcount, 1); 451 | } 452 | 453 | inline void Mat::release() 454 | { 455 | if (refcount && NCNN_XADD(refcount, -1) == 1) 456 | fastFree(data); 457 | 458 | dims = 0; 459 | data = 0; 460 | 461 | w = 0; 462 | h = 0; 463 | c = 0; 464 | 465 | cstep = 0; 466 | 467 | refcount = 0; 468 | } 469 | 470 | inline bool Mat::empty() const 471 | { 472 | return data == 0 || total() == 0; 473 | } 474 | 475 | inline size_t Mat::total() const 476 | { 477 | return cstep * c; 478 | } 479 | 480 | inline Mat Mat::channel(int c) 481 | { 482 | return Mat(w, h, data + cstep * c); 483 | } 484 | 485 | inline const Mat Mat::channel(int c) const 486 | { 487 | return Mat(w, h, data + cstep * c); 488 | } 489 | 490 | inline float* Mat::row(int y) 491 | { 492 | return data + w * y; 493 | } 494 | 495 | inline const float* Mat::row(int y) const 496 | { 497 | return data + w * y; 498 | } 499 | 500 | inline Mat::operator float*() 501 | { 502 | return data; 503 | } 504 | 505 | inline Mat::operator const float*() const 506 | { 507 | return data; 508 | } 509 | 510 | } // namespace ncnn 511 | 512 | #endif // NCNN_MAT_H 513 | -------------------------------------------------------------------------------- /ncnn_include/net.h: -------------------------------------------------------------------------------- 1 | // Tencent is pleased to support the open source community by making ncnn available. 2 | // 3 | // Copyright (C) 2017 THL A29 Limited, a Tencent company. All rights reserved. 4 | // 5 | // Licensed under the BSD 3-Clause License (the "License"); you may not use this file except 6 | // in compliance with the License. You may obtain a copy of the License at 7 | // 8 | // https://opensource.org/licenses/BSD-3-Clause 9 | // 10 | // Unless required by applicable law or agreed to in writing, software distributed 11 | // under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR 12 | // CONDITIONS OF ANY KIND, either express or implied. See the License for the 13 | // specific language governing permissions and limitations under the License. 14 | 15 | #ifndef NCNN_NET_H 16 | #define NCNN_NET_H 17 | 18 | #include 19 | #include 20 | #include "blob.h" 21 | #include "layer.h" 22 | #include "mat.h" 23 | #include "platform.h" 24 | 25 | namespace ncnn { 26 | 27 | class Extractor; 28 | class Net 29 | { 30 | public: 31 | // empty init 32 | Net(); 33 | // clear and destroy 34 | ~Net(); 35 | 36 | #if NCNN_STRING 37 | // register custom layer by layer type name 38 | // return 0 if success 39 | int register_custom_layer(const char* type, layer_creator_func creator); 40 | #endif // NCNN_STRING 41 | // register custom layer by layer type 42 | // return 0 if success 43 | int register_custom_layer(int index, layer_creator_func creator); 44 | 45 | #if NCNN_STDIO 46 | #if NCNN_STRING 47 | // load network structure from plain param file 48 | // return 0 if success 49 | int load_param(FILE* fp); 50 | int load_param(const char* protopath); 51 | #endif // NCNN_STRING 52 | // load network structure from binary param file 53 | // return 0 if success 54 | int load_param_bin(FILE* fp); 55 | int load_param_bin(const char* protopath); 56 | 57 | // load network weight data from model file 58 | // return 0 if success 59 | int load_model(FILE* fp); 60 | int load_model(const char* modelpath); 61 | #endif // NCNN_STDIO 62 | 63 | // load network structure from external memory 64 | // memory pointer must be 32-bit aligned 65 | // return bytes consumed 66 | int load_param(const unsigned char* mem); 67 | 68 | // reference network weight data from external memory 69 | // weight data is not copied but referenced 70 | // so external memory should be retained when used 71 | // memory pointer must be 32-bit aligned 72 | // return bytes consumed 73 | int load_model(const unsigned char* mem); 74 | 75 | // unload network structure and weight data 76 | void clear(); 77 | 78 | // construct an Extractor from network 79 | Extractor create_extractor() const; 80 | 81 | protected: 82 | friend class Extractor; 83 | #if NCNN_STRING 84 | int find_blob_index_by_name(const char* name) const; 85 | int find_layer_index_by_name(const char* name) const; 86 | int custom_layer_to_index(const char* type); 87 | #endif // NCNN_STRING 88 | Layer* create_custom_layer(int index); 89 | int forward_layer(int layer_index, std::vector& blob_mats, bool lightmode) const; 90 | 91 | protected: 92 | std::vector blobs; 93 | std::vector layers; 94 | 95 | std::vector custom_layer_registry; 96 | }; 97 | 98 | class Extractor 99 | { 100 | public: 101 | // enable light mode 102 | // intermediate blob will be recycled when enabled 103 | // disabled by default, but recommend to enable 104 | void set_light_mode(bool enable); 105 | 106 | // set thread count for this extractor 107 | // this will overwrite the global setting 108 | // default count is system depended 109 | void set_num_threads(int num_threads); 110 | 111 | #if NCNN_STRING 112 | // set input by blob name 113 | // return 0 if success 114 | int input(const char* blob_name, const Mat& in); 115 | 116 | // get result by blob name 117 | // return 0 if success 118 | int extract(const char* blob_name, Mat& feat); 119 | #endif // NCNN_STRING 120 | 121 | // set input by blob index 122 | // return 0 if success 123 | int input(int blob_index, const Mat& in); 124 | 125 | // get result by blob index 126 | // return 0 if success 127 | int extract(int blob_index, Mat& feat); 128 | 129 | protected: 130 | friend Extractor Net::create_extractor() const; 131 | Extractor(const Net* net, int blob_count); 132 | 133 | private: 134 | const Net* net; 135 | std::vector blob_mats; 136 | bool lightmode; 137 | int num_threads; 138 | }; 139 | 140 | } // namespace ncnn 141 | 142 | #endif // NCNN_NET_H 143 | -------------------------------------------------------------------------------- /ncnn_include/platform.h: -------------------------------------------------------------------------------- 1 | // Tencent is pleased to support the open source community by making ncnn available. 2 | // 3 | // Copyright (C) 2017 THL A29 Limited, a Tencent company. All rights reserved. 4 | // 5 | // Licensed under the BSD 3-Clause License (the "License"); you may not use this file except 6 | // in compliance with the License. You may obtain a copy of the License at 7 | // 8 | // https://opensource.org/licenses/BSD-3-Clause 9 | // 10 | // Unless required by applicable law or agreed to in writing, software distributed 11 | // under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR 12 | // CONDITIONS OF ANY KIND, either express or implied. See the License for the 13 | // specific language governing permissions and limitations under the License. 14 | 15 | #ifndef NCNN_PLATFORM_H 16 | #define NCNN_PLATFORM_H 17 | 18 | #define NCNN_STDIO 1 19 | #define NCNN_STRING 1 20 | #define NCNN_OPENCV 0 21 | 22 | #endif // NCNN_PLATFORM_H 23 | -------------------------------------------------------------------------------- /nms.h: -------------------------------------------------------------------------------- 1 | #ifndef NMS_H_ 2 | #define NMS_H_ 3 | 4 | #include 5 | #include 6 | 7 | template 8 | void nms(const T *pBoxes, const T *pScores, int nSample, double overlap, 9 | int &nPick, T* &boxes_nms, T* &scores_nms) { 10 | const int BOX_DIMS = 4; 11 | std::vector vPick(nSample); 12 | std::vector vArea(nSample); 13 | for (int i = 0; i < nSample; ++i) { 14 | vArea[i] = double( 15 | pBoxes[i * BOX_DIMS + 2] - pBoxes[i * BOX_DIMS + 0] + 1) 16 | * (pBoxes[i * BOX_DIMS + 3] - pBoxes[i * BOX_DIMS + 1] + 1); 17 | if (vArea[i] < 0) 18 | printf("Boxes area must >= 0"); 19 | } 20 | std::multimap scores; 21 | for (int i = 0; i < nSample; ++i) 22 | scores.insert(std::pair(pScores[i], i)); 23 | 24 | nPick = 0; 25 | do { 26 | int last = scores.rbegin()->second; 27 | vPick[nPick] = last; 28 | nPick += 1; 29 | 30 | for (typename std::multimap::iterator it = scores.begin(); 31 | it != scores.end();) { 32 | int it_idx = it->second; 33 | T xx1 = std::max(pBoxes[0 + BOX_DIMS * last], 34 | pBoxes[0 + BOX_DIMS * it_idx]); 35 | T yy1 = std::max(pBoxes[1 + BOX_DIMS * last], 36 | pBoxes[1 + BOX_DIMS * it_idx]); 37 | T xx2 = std::min(pBoxes[2 + BOX_DIMS * last], 38 | pBoxes[2 + BOX_DIMS * it_idx]); 39 | T yy2 = std::min(pBoxes[3 + BOX_DIMS * last], 40 | pBoxes[3 + BOX_DIMS * it_idx]); 41 | 42 | double w = std::max(T(0.0), xx2 - xx1 + 1), h = std::max(T(0.0), 43 | yy2 - yy1 + 1); 44 | 45 | double ov = w * h / (vArea[last] + vArea[it_idx] - w * h); 46 | 47 | if (ov > overlap) { 48 | it = scores.erase(it); 49 | } else { 50 | it++; 51 | } 52 | } 53 | 54 | } while (scores.size() != 0); 55 | if (boxes_nms != NULL) 56 | delete[] boxes_nms; 57 | boxes_nms = new T[nPick * BOX_DIMS]; 58 | if (scores_nms != NULL) 59 | delete[] scores_nms; 60 | scores_nms = new T[nPick]; 61 | for (int i = 0; i < nPick; ++i) { 62 | 63 | int index = vPick[i]; 64 | boxes_nms[i * BOX_DIMS + 0] = pBoxes[index * BOX_DIMS + 0]; 65 | boxes_nms[i * BOX_DIMS + 1] = pBoxes[index * BOX_DIMS + 1]; 66 | boxes_nms[i * BOX_DIMS + 2] = pBoxes[index * BOX_DIMS + 2]; 67 | boxes_nms[i * BOX_DIMS + 3] = pBoxes[index * BOX_DIMS + 3]; 68 | scores_nms[i] = pScores[index]; 69 | } 70 | } 71 | #endif -------------------------------------------------------------------------------- /proposal_test.ncnnproto: -------------------------------------------------------------------------------- 1 | 38 39 2 | Input data 0 1 data 3 224 224 3 | Convolution conv1_1 1 1 data conv1_1 64 3 1 1 1 1 1728 4 | ReLU relu1_1 1 1 conv1_1 conv1_1_relu1_1 0.000000 5 | Convolution conv1_2 1 1 conv1_1_relu1_1 conv1_2 64 3 1 1 1 1 36864 6 | ReLU relu1_2 1 1 conv1_2 conv1_2_relu1_2 0.000000 7 | Pooling pool1 1 1 conv1_2_relu1_2 pool1 0 2 2 0 0 8 | Convolution conv2_1 1 1 pool1 conv2_1 128 3 1 1 1 1 73728 9 | ReLU relu2_1 1 1 conv2_1 conv2_1_relu2_1 0.000000 10 | Convolution conv2_2 1 1 conv2_1_relu2_1 conv2_2 128 3 1 1 1 1 147456 11 | ReLU relu2_2 1 1 conv2_2 conv2_2_relu2_2 0.000000 12 | Pooling pool2 1 1 conv2_2_relu2_2 pool2 0 2 2 0 0 13 | Convolution conv3_1 1 1 pool2 conv3_1 256 3 1 1 1 1 294912 14 | ReLU relu3_1 1 1 conv3_1 conv3_1_relu3_1 0.000000 15 | Convolution conv3_2 1 1 conv3_1_relu3_1 conv3_2 256 3 1 1 1 1 589824 16 | ReLU relu3_2 1 1 conv3_2 conv3_2_relu3_2 0.000000 17 | Convolution conv3_3 1 1 conv3_2_relu3_2 conv3_3 256 3 1 1 1 1 589824 18 | ReLU relu3_3 1 1 conv3_3 conv3_3_relu3_3 0.000000 19 | Pooling pool3 1 1 conv3_3_relu3_3 pool3 0 2 2 0 0 20 | Convolution conv4_1 1 1 pool3 conv4_1 512 3 1 1 1 1 1179648 21 | ReLU relu4_1 1 1 conv4_1 conv4_1_relu4_1 0.000000 22 | Convolution conv4_2 1 1 conv4_1_relu4_1 conv4_2 512 3 1 1 1 1 2359296 23 | ReLU relu4_2 1 1 conv4_2 conv4_2_relu4_2 0.000000 24 | Convolution conv4_3 1 1 conv4_2_relu4_2 conv4_3 512 3 1 1 1 1 2359296 25 | ReLU relu4_3 1 1 conv4_3 conv4_3_relu4_3 0.000000 26 | Pooling pool4 1 1 conv4_3_relu4_3 pool4 0 2 2 0 0 27 | Convolution conv5_1 1 1 pool4 conv5_1 512 3 1 1 1 1 2359296 28 | ReLU relu5_1 1 1 conv5_1 conv5_1_relu5_1 0.000000 29 | Convolution conv5_2 1 1 conv5_1_relu5_1 conv5_2 512 3 1 1 1 1 2359296 30 | ReLU relu5_2 1 1 conv5_2 conv5_2_relu5_2 0.000000 31 | Convolution conv5_3 1 1 conv5_2_relu5_2 conv5_3 512 3 1 1 1 1 2359296 32 | ReLU relu5_3 1 1 conv5_3 conv5_3_relu5_3 0.000000 33 | Convolution conv_proposal1 1 1 conv5_3_relu5_3 conv_proposal1 512 3 1 1 1 1 2359296 34 | ReLU relu_proposal1 1 1 conv_proposal1 conv_proposal1_relu_proposal1 0.000000 35 | Split splitncnn_0 1 2 conv_proposal1_relu_proposal1 conv_proposal1_relu_proposal1_splitncnn_0 conv_proposal1_relu_proposal1_splitncnn_1 36 | Convolution proposal_cls_score 1 1 conv_proposal1_relu_proposal1_splitncnn_1 proposal_cls_score 18 1 1 1 0 1 9216 37 | Convolution proposal_bbox_pred 1 1 conv_proposal1_relu_proposal1_splitncnn_0 proposal_bbox_pred 36 1 1 1 0 1 18432 38 | Reshape proposal_cls_score_reshape 1 1 proposal_cls_score proposal_cls_score_reshape 0 -1 2 39 | Softmax proposal_cls_prob 1 1 proposal_cls_score_reshape proposal_cls_prob 40 | -------------------------------------------------------------------------------- /win/layer_declaration.h: -------------------------------------------------------------------------------- 1 | extern Layer* AbsVal_layer_creator(); 2 | extern Layer* ArgMax_layer_creator(); 3 | extern Layer* BatchNorm_layer_creator(); 4 | extern Layer* Bias_layer_creator(); 5 | extern Layer* BNLL_layer_creator(); 6 | extern Layer* Concat_layer_creator(); 7 | extern Layer* Convolution_x86_layer_creator(); 8 | extern Layer* Crop_layer_creator(); 9 | extern Layer* Deconvolution_layer_creator(); 10 | extern Layer* Dropout_layer_creator(); 11 | extern Layer* Eltwise_layer_creator(); 12 | extern Layer* ELU_layer_creator(); 13 | extern Layer* Embed_layer_creator(); 14 | extern Layer* Exp_layer_creator(); 15 | extern Layer* Flatten_layer_creator(); 16 | extern Layer* InnerProduct_layer_creator(); 17 | extern Layer* Input_layer_creator(); 18 | extern Layer* Log_layer_creator(); 19 | extern Layer* LRN_layer_creator(); 20 | extern Layer* MemoryData_layer_creator(); 21 | extern Layer* MVN_layer_creator(); 22 | extern Layer* Pooling_layer_creator(); 23 | extern Layer* Power_layer_creator(); 24 | extern Layer* PReLU_layer_creator(); 25 | extern Layer* Proposal_layer_creator(); 26 | extern Layer* Reduction_layer_creator(); 27 | extern Layer* ReLU_layer_creator(); 28 | extern Layer* Reshape_layer_creator(); 29 | extern Layer* ROIPooling_layer_creator(); 30 | extern Layer* Scale_layer_creator(); 31 | extern Layer* Sigmoid_layer_creator(); 32 | extern Layer* Slice_layer_creator(); 33 | extern Layer* Softmax_layer_creator(); 34 | extern Layer* Split_layer_creator(); 35 | extern Layer* SPP_layer_creator(); 36 | extern Layer* TanH_layer_creator(); 37 | extern Layer* Threshold_layer_creator(); 38 | extern Layer* Tile_layer_creator(); 39 | extern Layer* RNN_layer_creator(); 40 | extern Layer* LSTM_layer_creator(); 41 | -------------------------------------------------------------------------------- /win/layer_registry.h: -------------------------------------------------------------------------------- 1 | #if NCNN_STRING 2 | {"AbsVal",AbsVal_layer_creator}, 3 | #else 4 | {AbsVal_layer_creator}, 5 | #endif 6 | #if NCNN_STRING 7 | {"ArgMax",ArgMax_layer_creator}, 8 | #else 9 | {ArgMax_layer_creator}, 10 | #endif 11 | #if NCNN_STRING 12 | {"BatchNorm",BatchNorm_layer_creator}, 13 | #else 14 | {BatchNorm_layer_creator}, 15 | #endif 16 | #if NCNN_STRING 17 | {"Bias",Bias_layer_creator}, 18 | #else 19 | {Bias_layer_creator}, 20 | #endif 21 | #if NCNN_STRING 22 | {"BNLL",BNLL_layer_creator}, 23 | #else 24 | {BNLL_layer_creator}, 25 | #endif 26 | #if NCNN_STRING 27 | {"Concat",Concat_layer_creator}, 28 | #else 29 | {Concat_layer_creator}, 30 | #endif 31 | #if NCNN_STRING 32 | {"Convolution",Convolution_x86_layer_creator}, 33 | #else 34 | {Convolution_x86_layer_creator}, 35 | #endif 36 | #if NCNN_STRING 37 | {"Crop",Crop_layer_creator}, 38 | #else 39 | {Crop_layer_creator}, 40 | #endif 41 | #if NCNN_STRING 42 | {"Deconvolution",Deconvolution_layer_creator}, 43 | #else 44 | {Deconvolution_layer_creator}, 45 | #endif 46 | #if NCNN_STRING 47 | {"Dropout",Dropout_layer_creator}, 48 | #else 49 | {Dropout_layer_creator}, 50 | #endif 51 | #if NCNN_STRING 52 | {"Eltwise",Eltwise_layer_creator}, 53 | #else 54 | {Eltwise_layer_creator}, 55 | #endif 56 | #if NCNN_STRING 57 | {"ELU",ELU_layer_creator}, 58 | #else 59 | {ELU_layer_creator}, 60 | #endif 61 | #if NCNN_STRING 62 | {"Embed",Embed_layer_creator}, 63 | #else 64 | {Embed_layer_creator}, 65 | #endif 66 | #if NCNN_STRING 67 | {"Exp",Exp_layer_creator}, 68 | #else 69 | {Exp_layer_creator}, 70 | #endif 71 | #if NCNN_STRING 72 | {"Flatten",Flatten_layer_creator}, 73 | #else 74 | {Flatten_layer_creator}, 75 | #endif 76 | #if NCNN_STRING 77 | {"InnerProduct",InnerProduct_layer_creator}, 78 | #else 79 | {InnerProduct_layer_creator}, 80 | #endif 81 | #if NCNN_STRING 82 | {"Input",Input_layer_creator}, 83 | #else 84 | {Input_layer_creator}, 85 | #endif 86 | #if NCNN_STRING 87 | {"Log",Log_layer_creator}, 88 | #else 89 | {Log_layer_creator}, 90 | #endif 91 | #if NCNN_STRING 92 | {"LRN",LRN_layer_creator}, 93 | #else 94 | {LRN_layer_creator}, 95 | #endif 96 | #if NCNN_STRING 97 | {"MemoryData",MemoryData_layer_creator}, 98 | #else 99 | {MemoryData_layer_creator}, 100 | #endif 101 | #if NCNN_STRING 102 | {"MVN",MVN_layer_creator}, 103 | #else 104 | {MVN_layer_creator}, 105 | #endif 106 | #if NCNN_STRING 107 | {"Pooling",Pooling_layer_creator}, 108 | #else 109 | {Pooling_layer_creator}, 110 | #endif 111 | #if NCNN_STRING 112 | {"Power",Power_layer_creator}, 113 | #else 114 | {Power_layer_creator}, 115 | #endif 116 | #if NCNN_STRING 117 | {"PReLU",PReLU_layer_creator}, 118 | #else 119 | {PReLU_layer_creator}, 120 | #endif 121 | #if NCNN_STRING 122 | {"Proposal",Proposal_layer_creator}, 123 | #else 124 | {Proposal_layer_creator}, 125 | #endif 126 | #if NCNN_STRING 127 | {"Reduction",Reduction_layer_creator}, 128 | #else 129 | {Reduction_layer_creator}, 130 | #endif 131 | #if NCNN_STRING 132 | {"ReLU",ReLU_layer_creator}, 133 | #else 134 | {ReLU_layer_creator}, 135 | #endif 136 | #if NCNN_STRING 137 | {"Reshape",Reshape_layer_creator}, 138 | #else 139 | {Reshape_layer_creator}, 140 | #endif 141 | #if NCNN_STRING 142 | {"ROIPooling",ROIPooling_layer_creator}, 143 | #else 144 | {ROIPooling_layer_creator}, 145 | #endif 146 | #if NCNN_STRING 147 | {"Scale",Scale_layer_creator}, 148 | #else 149 | {Scale_layer_creator}, 150 | #endif 151 | #if NCNN_STRING 152 | {"Sigmoid",Sigmoid_layer_creator}, 153 | #else 154 | {Sigmoid_layer_creator}, 155 | #endif 156 | #if NCNN_STRING 157 | {"Slice",Slice_layer_creator}, 158 | #else 159 | {Slice_layer_creator}, 160 | #endif 161 | #if NCNN_STRING 162 | {"Softmax",Softmax_layer_creator}, 163 | #else 164 | {Softmax_layer_creator}, 165 | #endif 166 | #if NCNN_STRING 167 | {"Split",Split_layer_creator}, 168 | #else 169 | {Split_layer_creator}, 170 | #endif 171 | #if NCNN_STRING 172 | {"SPP",SPP_layer_creator}, 173 | #else 174 | {SPP_layer_creator}, 175 | #endif 176 | #if NCNN_STRING 177 | {"TanH",TanH_layer_creator}, 178 | #else 179 | {TanH_layer_creator}, 180 | #endif 181 | #if NCNN_STRING 182 | {"Threshold",Threshold_layer_creator}, 183 | #else 184 | {Threshold_layer_creator}, 185 | #endif 186 | #if NCNN_STRING 187 | {"Tile",Tile_layer_creator}, 188 | #else 189 | {Tile_layer_creator}, 190 | #endif 191 | #if NCNN_STRING 192 | {"RNN",RNN_layer_creator}, 193 | #else 194 | {RNN_layer_creator}, 195 | #endif 196 | #if NCNN_STRING 197 | {"LSTM",LSTM_layer_creator}, 198 | #else 199 | {LSTM_layer_creator}, 200 | #endif 201 | -------------------------------------------------------------------------------- /win/platform.h: -------------------------------------------------------------------------------- 1 | // Tencent is pleased to support the open source community by making ncnn available. 2 | // 3 | // Copyright (C) 2017 THL A29 Limited, a Tencent company. All rights reserved. 4 | // 5 | // Licensed under the BSD 3-Clause License (the "License"); you may not use this file except 6 | // in compliance with the License. You may obtain a copy of the License at 7 | // 8 | // https://opensource.org/licenses/BSD-3-Clause 9 | // 10 | // Unless required by applicable law or agreed to in writing, software distributed 11 | // under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR 12 | // CONDITIONS OF ANY KIND, either express or implied. See the License for the 13 | // specific language governing permissions and limitations under the License. 14 | 15 | #ifndef NCNN_PLATFORM_H 16 | #define NCNN_PLATFORM_H 17 | 18 | #define NCNN_STDIO 1 19 | #define NCNN_STRING 1 20 | #define NCNN_OPENCV 0 21 | 22 | #endif // NCNN_PLATFORM_H 23 | --------------------------------------------------------------------------------