Toybrick

标题: yolov3 yolov3_tiny C++ 多线程camera版本 [打印本页]

作者: eeyeh    时间: 2019-4-22 20:03
标题: yolov3 yolov3_tiny C++ 多线程camera版本
本帖最后由 eeyeh 于 2019-6-27 19:32 编辑

yolov3_416 yolov3_tiny_416多线程C++版本, darknet框架分Fetch&dispaly, detect(NPU inference), process(output转换, 后处理, 参照darknet demo.c)。
代码连接在最后面, 本人新手..代码写的可能有点差劲, 请前辈们修改指正。
yolov3_416, 量化模式asymmetric-u8, 平均每秒7.6帧左右(摄像头数据, 本地视频7.9帧左右), 平均每帧用时132ms, 某些帧最高能达到9帧速率。
Detect线程包含set input, inference, get output, 共118.8ms, 其中用rknn api查询NPU inference时间87.4ms(NPU上比较稳定)。
fetch&display 25.4ms, process 28.2ms  。帧率受限于Detect线程。
yolov3_tiny_416, 量化模式asymmetric-u8, 平均每秒30帧左右(摄像头数据, 本地视频能上50), 某些帧最高能达到40~50帧速率。
Detect线程包含set input, inference, get output, 共17.4ms, 其中用rknn api查询NPU inference时间5ms(NPU上时间比较稳定)。
Fetch&display 37.4ms, process 31.9ms。
帧率受限于CPU上的其他处理(应该是受限于摄像头数据读取), 帧率波动较大。


参照darknet的demo.c写的, 但感觉还是有点问题, 线程处理的话是不是对CPU分时间片, 这样的话是不是实际上还是等效于只分了NPU和CPU两部分
因此对于yolov3_tiny受限于CPU应该还能优化。
大家可以参照momo的多线程ssd修改http://t.rock-chips.com/forum.php?mod=viewthread&tid=349&extra=page%3D1
链接代码支持线程绑定CPU,两个大核用于NPU深度学习处理, 正在学习中, 吸收完毕后再修改代码。 (三楼已有支持多线程绑定CPU的代码,支持摄像头和本地视频处理;两个大核处理NPU,其他小核处理图像读取和显示;640*480*3的数据流,帧率约55fps;)菜鸟新手, 大家修改指教~。
------
参照多线程绑定CPU, Yolov3_416已能够跑到11帧。
  1. #include <stdio.h>
  2. #include <stdint.h>
  3. #include <stdlib.h>
  4. #include <fstream>
  5. #include <iostream>
  6. #include <sys/time.h>

  7. #include "rknn_api.h"
  8. #include "opencv2/core/core.hpp"
  9. #include "opencv2/imgproc/imgproc.hpp"
  10. #include "opencv2/highgui/highgui.hpp"

  11. using namespace std;
  12. using namespace cv;

  13. int demo_done=0;
  14. const int net_width=416;        //网络输入大小,实际上计算IOU需要根据原图大小,此程序简化直接根据416*416来算
  15. const int net_height=416;
  16. const int img_channels=3;
  17. cv::Mat img[3];    //IMREAD_COLOR=1 default  BGR
  18. int buff_index=0;
  19. int outputs_index=0;
  20. cv::VideoCapture cap;
  21. rknn_context ctx;

  22. rknn_input inputs[1];
  23. rknn_output outputs[2][3];
  24. rknn_perf_detail perf_detail;
  25. rknn_perf_run perf_run;
  26. rknn_tensor_attr outputs_attr[3];

  27. Scalar colorArray[10]={
  28.         Scalar(139,0,0,255),
  29.         Scalar(139,0,139,255),
  30.         Scalar(0,0,139,255),
  31.         Scalar(0,100,0,255),
  32.         Scalar(139,139,0,255),
  33.         Scalar(209,206,0,255),
  34.         Scalar(0,127,255,255),
  35.         Scalar(139,61,72,255),
  36.         Scalar(0,255,0,255),
  37.         Scalar(255,0,0,255),
  38. };

  39. static string labels[80]={"person", "bicycle", "car","motorbike ","aeroplane ","bus ","train","truck ","boat","traffic light","fire hydrant","stop sign ","parking meter","bench","bird","cat","dog ","horse ","sheep","cow","elephant","bear","zebra ","giraffe","backpack","umbrella","handbag","tie","suitcase","frisbee","skis","snowboard","sports ball","kite","baseball bat","baseball glove","skateboard","surfboard","tennis racket","bottle","wine glass","cup","fork","knife ","spoon","bowl","banana","apple","sandwich","orange","broccoli","carrot","hot dog","pizza ","donut","cake","chair","sofa","pottedplant","bed","diningtable","toilet ","tvmonitor","laptop","mouse","remote ","keyboard ","cell phone","microwave ","oven ","toaster","sink","refrigerator ","book","clock","vase","scissors ","teddy bear ","hair drier", "toothbrush "};

  40. static int GRID0=13;
  41. static int GRID1=26;
  42. static int GRID2=52;
  43. static int nclasses=80;
  44. static int nyolo=3; //n yolo layers;
  45. static int nanchor=3; //n anchor per yolo layer

  46. static int nboxes_0=GRID0*GRID0*nanchor;
  47. static int nboxes_1=GRID1*GRID1*nanchor;
  48. static int nboxes_2=GRID2*GRID2*nanchor;

  49. static int nboxes_total=nboxes_0+nboxes_1+nboxes_2;

  50. float OBJ_THRESH=0.2;
  51. float DRAW_CLASS_THRESH=0.2;
  52. float NMS_THRESH=0.4;  //darknet demo nms=0.4


  53. typedef struct{
  54.         float x,y,w,h;
  55. }box;

  56. typedef struct detection{
  57.     box bbox;
  58.     int classes;
  59.     float *prob;
  60.     float objectness;
  61.     int sort_class;
  62. } detection;

  63. detection* dets=0;

  64. void free_detections(detection *dets, int n)
  65. {
  66.     int i;
  67.     for(i = 0; i < n; ++i){
  68.         free(dets.prob);
  69.     }
  70.     free(dets);
  71. }

  72. double what_time_is_it_now()
  73. {
  74.     struct timeval time;
  75.     if (gettimeofday(&time,NULL)){
  76.         return 0;
  77.     }
  78.     return (double)time.tv_sec + (double)time.tv_usec * .000001;
  79. }


  80. box get_yolo_box(float *x, float *biases, int n, int index, int i, int j, int lw, int lh, int netw, int neth, int stride)
  81. {
  82.     box b;
  83.     b.x = (i + x[index + 0*stride]) / lw;
  84.     b.y = (j + x[index + 1*stride]) / lh;
  85.     b.w = exp(x[index + 2*stride]) * biases[2*n]   / netw;
  86.     b.h = exp(x[index + 3*stride]) * biases[2*n+1] / neth;
  87.     return b;
  88. }

  89. detection *get_network_boxes(float *predictions, int netw,int neth,int GRID,int* masks, float* anchors, int box_off)
  90. {
  91.         int lw=GRID;
  92.         int lh=GRID;
  93.         int nboxes=GRID*GRID*nanchor;
  94.         int LISTSIZE=1+4+nclasses;
  95.         //darkent output排列格式: box顺序为先grid再anchor
  96.         //1个anchor: 7*7*x+7*7*y+7*7*w+7*7*w+7*7*obj+7*7*classes1+7*7*classes2..+7*7*classes80,共3个anchor
  97.         //x和y(先做,或者放在后面转换到实际坐标这一步中也行),以及obj和classes做logisic
  98.         //xy做logistic
  99.         for(int n=0;n<nanchor;n++){
  100.                 int index=n*lw*lh*LISTSIZE;
  101.                 int index_end=index+2*lw*lh;
  102.                 for(int i=index;i<index_end;i++)
  103.                         predictions=1./(1.+exp(-predictions));                        
  104.         }
  105.         //类别和obj做logistic
  106.         for(int n=0;n<nanchor;n++){
  107.                 int index=n*lw*lh*LISTSIZE+4*lw*lh;
  108.                 int index_end=index+(1+nclasses)*lw*lh;
  109.                 for(int i=index;i<index_end;i++){
  110.                         predictions=1./(1.+exp(-predictions));               
  111.                 }
  112.         }
  113.         //dets将outpus重排列,dets为第i个框,box顺序为先anchor再grid

  114.         int count=box_off;
  115.         for(int i=0;i<lw*lh;i++){
  116.                 int row=i/lw;
  117.                 int col=i%lw;
  118.                 for(int n=0;n<nanchor;n++){
  119.                         int box_loc=n*lw*lh+i;  
  120.                         int box_index=n*lw*lh*LISTSIZE+i;            //box的x索引,ywh索引只要依次加上lw*lh
  121.                         int obj_index=box_index+4*lw*lh;
  122.                         float objectness=predictions[obj_index];
  123.                         if(objectness<OBJ_THRESH) continue;
  124.                         dets[count].objectness=objectness;
  125.                         dets[count].classes=nclasses;
  126.                         dets[count].bbox=get_yolo_box(predictions,anchors,masks[n],box_index,col,row,lw,lh,netw,neth,lw*lh);
  127.                         for(int j=0;j<nclasses;j++){
  128.                                 int class_index=box_index+(5+j)*lw*lh;
  129.                                 float prob=objectness*predictions[class_index];
  130.                                 dets[count].prob[j]=prob;
  131.                         }
  132.                         ++count;
  133.                 }
  134.         }
  135.         //cout<<"count: "<<count-box_off<<"\n";
  136.     return dets;
  137. }

  138. detection* outputs_transform(rknn_output rknn_outputs[], int net_width, int net_height){
  139.         float* output_0=(float*)rknn_outputs[0].buf;
  140.         float* output_1=(float*)rknn_outputs[1].buf;
  141.         float* output_2=(float*)rknn_outputs[2].buf;
  142.     int masks_0[3] = {6, 7, 8};
  143.     int masks_1[3] = {3, 4, 5};
  144.         int masks_2[3] = {0, 1, 2};
  145.         //float anchors[12] = {10, 14, 23, 27, 37, 58, 81, 82, 135, 169, 344, 319};
  146.         float anchors[18] = {10,13,16,30,33,23,30,61,62,45,59,119,116,90,156,198,373,326};
  147.         //输出xywh均在0-1范围内
  148.         get_network_boxes(output_0,net_width,net_height,GRID0,masks_0,anchors,0);
  149.         get_network_boxes(output_1,net_width,net_height,GRID1,masks_1,anchors,nboxes_0);
  150.         get_network_boxes(output_2,net_width,net_height,GRID2,masks_1,anchors,nboxes_0+nboxes_1);
  151.         return dets;

  152. }

  153. float overlap(float x1,float w1,float x2,float w2){
  154.         float l1=x1-w1/2;
  155.         float l2=x2-w2/2;
  156.         float left=l1>l2? l1:l2;
  157.         float r1=x1+w1/2;
  158.         float r2=x2+w2/2;
  159.         float right=r1<r2? r1:r2;
  160.         return right-left;
  161. }

  162. float box_intersection(box a, box b)
  163. {
  164.     float w = overlap(a.x, a.w, b.x, b.w);
  165.     float h = overlap(a.y, a.h, b.y, b.h);
  166.     if(w < 0 || h < 0) return 0;
  167.     float area = w*h;
  168.     return area;
  169. }

  170. float box_union(box a, box b)
  171. {
  172.     float i = box_intersection(a, b);
  173.     float u = a.w*a.h + b.w*b.h - i;
  174.     return u;
  175. }

  176. float box_iou(box a, box b)
  177. {
  178.     return box_intersection(a, b)/box_union(a, b);
  179. }

  180. int nms_comparator(const void *pa, const void *pb)
  181. {
  182.     detection a = *(detection *)pa;
  183.     detection b = *(detection *)pb;
  184.     float diff = 0;
  185.     if(b.sort_class >= 0){
  186.         diff = a.prob[b.sort_class] - b.prob[b.sort_class];
  187.     } else {
  188.         diff = a.objectness - b.objectness;
  189.     }
  190.     if(diff < 0) return 1;
  191.     else if(diff > 0) return -1;
  192.     return 0;
  193. }
  194. int do_nms_sort(detection *dets, int total, int classes, float thresh)
  195. {
  196.     int i, j, k;
  197.     k = total-1;
  198.     for(i = 0; i <= k; ++i){
  199.         if(dets.objectness == 0){
  200.             detection swap = dets;
  201.             dets = dets[k];
  202.             dets[k] = swap;
  203.             --k;
  204.             --i;
  205.         }
  206.     }
  207.     total = k+1;
  208.         //cout<<"total after OBJ_THRESH: "<<total<<"\n";

  209.     for(k = 0; k < classes; ++k){
  210.         for(i = 0; i < total; ++i){
  211.             dets.sort_class = k;
  212.         }
  213.         qsort(dets, total, sizeof(detection), nms_comparator);
  214.         for(i = 0; i < total; ++i){
  215.             if(dets.prob[k] == 0) continue;
  216.             box a = dets.bbox;
  217.             for(j = i+1; j < total; ++j){
  218.                 box b = dets[j].bbox;
  219.                 if (box_iou(a, b) > thresh){
  220.                     dets[j].prob[k] = 0;
  221.                 }
  222.             }
  223.         }
  224.     }
  225.         return total;
  226. }

  227. //简化的nms, 只对obj做了nms,未对每个类做nms
  228. //对class进行nms的函数见darknet do_nms_sort
  229. int do_nms_obj(detection *dets, int total, int classes, float thresh)
  230. {
  231.     int i, j, k;
  232.     k = total-1;
  233.         //cout<<"k: "<<k<<"\n";
  234.     for(i = 0; i <= k; ++i){
  235.         if(dets.objectness == 0){
  236.             detection swap = dets;
  237.             dets = dets[k];
  238.             dets[k] = swap;
  239.             --k;
  240.             --i;
  241.         }
  242.     }
  243.     total = k+1;
  244.         //cout<<"total after OBJ_THRESH: "<<total<<"\n";
  245.     for(i = 0; i < total; ++i){
  246.         dets.sort_class = -1;
  247.     }

  248.     qsort(dets, total, sizeof(detection), nms_comparator);  //此处nms sort_classes<0,并未对类别nms, 直接对obj做nms
  249.     for(i = 0; i < total; ++i){
  250.         if(dets.objectness == 0) continue;
  251.         box a = dets.bbox;
  252.         for(j = i+1; j < total; ++j){
  253.             if(dets[j].objectness == 0) continue;
  254.             box b = dets[j].bbox;
  255.             if (box_iou(a, b) > thresh){
  256.                 dets[j].objectness = 0;
  257.                 for(k = 0; k < classes; ++k){
  258.                     dets[j].prob[k] = 0;
  259.                 }
  260.             }
  261.         }
  262.     }
  263.         return total;
  264. }

  265. int draw_image(cv::Mat img,detection* dets,int total,float thresh){
  266.         cv::cvtColor(img, img, cv::COLOR_RGB2BGR);
  267.         for(int i=0;i<total;i++){
  268.                 char labelstr[4096]={0};
  269.                 int class_=-1;
  270.                 int topclass=-1;
  271.                 float topclass_score=0;
  272.                 if(dets.objectness==0) continue;
  273.                 for(int j=0;j<nclasses;j++){
  274.                         if(dets.prob[j]>thresh){
  275.                                 if(topclass_score<dets.prob[j]){
  276.                                         topclass_score=dets.prob[j];
  277.                                         topclass=j;
  278.                                 }
  279.                                 if(class_<0){
  280.                                         strcat(labelstr,labels[j].data());
  281.                                         class_=j;
  282.                                 }
  283.                                 else{
  284.                                         strcat(labelstr,",");
  285.                                         strcat(labelstr,labels[j].data());
  286.                                 }
  287.                                 printf("%s: %.02f%%\n",labels[j].data(),dets.prob[j]*100);
  288.                         }
  289.                 }
  290.                 //如果class>0说明框中有物体,需画框
  291.                 if(class_>=0){
  292.                         box b=dets.bbox;
  293.                         int x1 =(b.x-b.w/2.)*img.cols;
  294.                         int x2=(b.x+b.w/2.)*img.cols;
  295.                         int y1=(b.y-b.h/2.)*img.rows;
  296.                         int y2=(b.y+b.h/2.)*img.rows;

  297.             if(x1  < 0) x1  = 0;
  298.             if(x2> img.cols-1) x2 = img.cols-1;
  299.             if(y1 < 0) y1 = 0;
  300.             if(x2 > img.rows-1) x2 = img.rows-1;
  301.                         std::cout << labels[topclass] << "\t@ (" << x1 << ", " << y1 << ") (" << x2 << ", " << y2 << ")" << "\n";

  302.             rectangle(img, Point(x1, y1), Point(x2, y2), colorArray[class_%10], 3);
  303.             putText(img, labelstr, Point(x1, y1 - 12), 1, 2, Scalar(0, 255, 0, 255));
  304.             }
  305.                 }
  306.         
  307.         //imwrite("out.jpg",img);
  308.         return 0;
  309. }

  310. void *display_in_thread(void *ptr){
  311.         double start_time,end_time;
  312.         start_time=what_time_is_it_now();
  313.         cv::Mat img_show;
  314.         img_show=img[(buff_index)%3];
  315.         //cv::resize(img[(buff_index)%3],img_show,cv::Size(600,600),0,0,cv::INTER_LINEAR);
  316.         cv::imshow("yolov3_tiny",img_show);
  317.         int c = cv::waitKey(1);
  318.     if (c != -1) c = c%256;
  319.     if (c == 27) {
  320.         demo_done = 1;
  321.         return 0;
  322.     } else if (c == 82) {
  323.         DRAW_CLASS_THRESH += .02;
  324.     } else if (c == 84) {
  325.         DRAW_CLASS_THRESH -= .02;
  326.         if(DRAW_CLASS_THRESH <= .02) DRAW_CLASS_THRESH = .02;
  327.     } else if (c == 83) {
  328.         NMS_THRESH += .02;
  329.     } else if (c == 81) {
  330.         NMS_THRESH -= .02;
  331.         if(NMS_THRESH <= .0) NMS_THRESH = .0;
  332.     }
  333.         end_time=what_time_is_it_now();
  334.         cout<<"display thread time:"<<(end_time-start_time)*1000<<" ms\n";
  335.         return 0;

  336. }

  337. void *fetch_in_thread(void *ptr){
  338.         double start_time,end_time;
  339.         start_time=what_time_is_it_now();
  340.         cv::Mat frame;
  341.         cap>>frame;
  342.     if(!frame.data) {
  343.         printf("fetch frame fail!\n");
  344.         return 0;
  345.     }
  346.     if(frame.cols != net_width || frame.rows != net_height)
  347.         cv::resize(frame, frame, cv::Size(net_width, net_height), (0, 0), (0, 0), cv::INTER_LINEAR);
  348.         //BGR->RGB
  349.         cv::cvtColor(frame, img[buff_index], cv::COLOR_BGR2RGB);
  350.         //cv::imshow("camera",frame);
  351.         end_time=what_time_is_it_now();
  352.         cout<<"fetch thread time:"<<(end_time-start_time)*1000<<" ms\n";
  353.         return 0;
  354. }

  355. void *process_in_thread(void *ptr){
  356.         double start_time,end_time;
  357.         start_time=what_time_is_it_now();
  358.         int nboxes_left=0;
  359.         //每次要重新清零, 否则会残留上次检测结果
  360.         for(int i=0;i<nboxes_total;++i){
  361.                 dets.objectness=0;
  362.         }
  363.         outputs_transform(outputs[(outputs_index+1)%2],net_width,net_height);
  364.         nboxes_left=do_nms_sort(dets,nboxes_total,nclasses,NMS_THRESH);
  365.         //nboxes_left=do_nms_obj(dets,nboxes_total,nclasses,NMS_THRESH);
  366.         draw_image(img[(buff_index+2)%3],dets,nboxes_left,DRAW_CLASS_THRESH);
  367.         rknn_outputs_release(ctx,3,outputs[(outputs_index+1)%2]);
  368.         end_time=what_time_is_it_now();
  369.         cout<<"process thread time:"<<(end_time-start_time)*1000<<" ms\n";
  370.         return 0;

  371. }

  372. void *detect_in_thread(void *ptr){
  373.         double start_time,end_time;
  374.         start_time=what_time_is_it_now();
  375.         inputs[0].buf = img[(buff_index+2)%3].data;
  376.         int ret = rknn_inputs_set(ctx, 1, inputs);
  377.         if(ret < 0) {
  378.                 printf("rknn_input_set fail! ret=%d\n", ret);
  379.                 goto Error;
  380.         }
  381.         //run
  382.     ret = rknn_run(ctx, nullptr);
  383.     if(ret < 0) {
  384.         printf("rknn_run fail! ret=%d\n", ret);
  385.         goto Error;
  386.     }
  387.         ret = rknn_outputs_get(ctx, 3, outputs[outputs_index], NULL);
  388.         if(ret < 0) {
  389.                 printf("rknn_outputs_get fail! ret=%d\n", ret);
  390.                 goto Error;
  391.         }
  392.         //if(outputs[outputs_index][0].size != outputs_attr[0].n_elems*sizeof(float)|| outputs[outputs_index][1].size != outputs_attr[1].n_elems*sizeof(float)|| outputs[outputs_index][2].size != outputs_attr[2].n_elems*sizeof(float)){
  393.         //        printf("outputs_size!=outpus_attr\n");
  394.         //        goto Error;
  395.         //}
  396.         //查询各层时间
  397.         //ret = rknn_query(ctx, RKNN_QUERY_PERF_DETAIL, &perf_detail,sizeof(rknn_perf_detail));
  398.         //printf("%s\n", perf_detail.perf_data);
  399.         //查询单帧推理时间
  400.         //ret = rknn_query(ctx, RKNN_QUERY_PERF_RUN, &perf_run, sizeof(rknn_perf_run));
  401.         //printf("NPU run time: %ld us\n", perf_run.run_duration);
  402.         end_time=what_time_is_it_now();
  403.         cout<<"detect thread time:"<<(end_time-start_time)*1000<<" ms\n";
  404.         return 0;
  405.         Error:
  406.                 if(ctx) rknn_destroy(ctx);
  407.         return 0;
  408. }

  409. int main(int argc, char** argb){
  410.         const char *model_path = "../tmp/yolov3.rknn";
  411.         cv::Mat frame;
  412.         cv::namedWindow("yolov3_tiny");
  413.         //cv::namedWindow("camera");
  414.         double begin,end,real_fps;
  415.         int frame_count=0;

  416.         //alloc total dets
  417.         dets =(detection*) calloc(nboxes_total,sizeof(detection));
  418.         for(int i=0;i<nboxes_total;++i){
  419.                 dets.prob=(float*) calloc(nclasses,sizeof(float));
  420.         }
  421.         
  422.     // Load model
  423.     FILE *fp = fopen(model_path, "rb");
  424.     if(fp == NULL) {
  425.         printf("fopen %s fail!\n", model_path);
  426.         return -1;
  427.     }
  428.     fseek(fp, 0, SEEK_END);   //fp指向end,fseek(FILE *stream, long offset, int fromwhere);
  429.     int model_len = ftell(fp);   //相对文件首偏移
  430.     void *model = malloc(model_len);
  431.     fseek(fp, 0, SEEK_SET);   //SEEK_SET为文件头
  432.     if(model_len != fread(model, 1, model_len, fp)) {
  433.         printf("fread %s fail!\n", model_path);
  434.         free(model);
  435.         return -1;
  436.     }
  437.         cout<<"model load done\n";

  438.         int ret=0;
  439.         rknn_input_output_num io_num;

  440.         //init
  441.         ret=rknn_init(&ctx,model,model_len,RKNN_FLAG_PRIOR_MEDIUM);//优先级
  442.         //ret=rknn_init(&ctx,model,model_len,RKNN_FLAG_PRIOR_MEDIUM | RKNN_FLAG_COLLECT_PERF_MASK);//优先级
  443.         if(ret < 0) {
  444.         printf("rknn_init fail! ret=%d\n", ret);
  445.         goto Error;
  446.     }
  447.         printf("rknn_init done\n");

  448.         //rknn input output num
  449.         ret = rknn_query(ctx,RKNN_QUERY_IN_OUT_NUM,&io_num,sizeof(io_num));
  450.         if(ret < 0) {
  451.         printf("rknn_query fail! ret=%d\n", ret);
  452.         goto Error;
  453.     }
  454.         cout<<"io_num query done\n";
  455.         cout<<"input num: "<<io_num.n_input<<";  ";
  456.         cout<<"output num: "<<io_num.n_output<<";  \n";
  457.         //rknn inputs
  458.         inputs[0].index = 0;
  459.         inputs[0].size = net_width * net_height * img_channels;
  460.         inputs[0].pass_through = false;         //需要type和fmt
  461.         inputs[0].type = RKNN_TENSOR_UINT8;
  462.         inputs[0].fmt = RKNN_TENSOR_NHWC;

  463.         //rknn outputs
  464.         outputs[0][0].want_float = true;
  465.         outputs[0][0].is_prealloc = false;
  466.         outputs[0][1].want_float = true;
  467.         outputs[0][1].is_prealloc = false;
  468.         outputs[0][2].want_float = true;
  469.         outputs[0][2].is_prealloc = false;
  470.         
  471.         outputs[1][0].want_float = true;
  472.         outputs[1][0].is_prealloc = false;
  473.         outputs[1][1].want_float = true;
  474.         outputs[1][1].is_prealloc = false;
  475.         outputs[1][2].want_float = true;
  476.         outputs[1][2].is_prealloc = false;
  477.         //rknn outputs_attr
  478.         outputs_attr[0].index = 0;
  479.     ret = rknn_query(ctx, RKNN_QUERY_OUTPUT_ATTR, &(outputs_attr[0]), sizeof(outputs_attr[0]));
  480.     if(ret < 0) {
  481.         printf("rknn_query fail! ret=%d\n", ret);
  482.         goto Error;
  483.     }
  484.     outputs_attr[1].index = 1;
  485.     ret = rknn_query(ctx, RKNN_QUERY_OUTPUT_ATTR, &(outputs_attr[1]), sizeof(outputs_attr[1]));
  486.     if(ret < 0) {
  487.         printf("rknn_query fail! ret=%d\n", ret);
  488.         goto Error;
  489.     }
  490.         outputs_attr[2].index = 2;
  491.     ret = rknn_query(ctx, RKNN_QUERY_OUTPUT_ATTR, &(outputs_attr[2]), sizeof(outputs_attr[2]));
  492.     if(ret < 0) {
  493.         printf("rknn_query fail! ret=%d\n", ret);
  494.         goto Error;
  495.     }

  496.         pthread_t detect_thread;
  497.         pthread_t process_thread;
  498.         cap.open("/dev/video8");
  499.         if(!cap.isOpened()){
  500.                 return -1;
  501.         }
  502.         cout<<"camera open done\n";
  503.         
  504.         cap>>frame;
  505.         if(!frame.data) {
  506.         printf("fetch frame fail!\n");
  507.         return 0;
  508.     }
  509.     if(frame.cols != net_width || frame.rows != net_height)
  510.         cv::resize(frame, frame, cv::Size(net_width, net_height), (0, 0), (0, 0), cv::INTER_LINEAR);
  511.     //BGR->RGB
  512.     cv::cvtColor(frame, frame, cv::COLOR_BGR2RGB);
  513.     img[0]=frame.clone();
  514.     img[1]=frame.clone();
  515.     img[2]=frame.clone();
  516.     detect_in_thread(0);
  517.     cout<<"first detect done\n";

  518.     begin=what_time_is_it_now();
  519.     while(!demo_done){
  520.             double start_time,end_time,fps;
  521.             start_time=what_time_is_it_now();
  522.             clock_t start,end;
  523.             outputs_index=(outputs_index+1)%2;
  524.             buff_index=(buff_index+1)%3;
  525.         
  526.             if(pthread_create(&process_thread,0,process_in_thread,0)) {
  527.                     printf("Thread process creation failed");
  528.                     break;
  529.            }
  530.            if(pthread_create(&detect_thread,0,detect_in_thread,0)) {
  531.                 printf("Thread detect creation failed");
  532.                 break;
  533.            }
复制代码
















作者: qiu    时间: 2019-4-24 08:35
多谢分享
作者: momo    时间: 2019-4-24 11:06
标题: C++多线程yolov3_tiny例程
本帖最后由 momo 于 2019-4-24 13:20 编辑

这个版本在楼主的基础上修改的,支持多线程绑定CPU,支持摄像头和本地视频处理;两个大核处理NPU,其他小核处理图像读取和显示;
640*480*3的数据流,帧率约55fps;



作者: momo    时间: 2019-4-24 13:19
hisping 发表于 2019-4-24 11:21
你这个压缩文件好像损坏了,我下载下来打不开。。。

我重新传一遍
作者: eeyeh    时间: 2019-4-24 19:58
本帖最后由 eeyeh 于 2019-4-26 20:22 编辑
momo 发表于 2019-4-24 11:06
这个版本在楼主的基础上修改的,支持多线程绑定CPU,支持摄像头和本地视频处理;两个大核处理NPU,其他小核 ...
                                         
作者: MinskyLee    时间: 2019-5-6 20:30
楼主,为什么我运行你的代码输出
model load done
rknn init done
io_num query done
input_num:1; output num:3;
camera open done
然后报rknn input_set failed! ret=-5的错
作者: eeyeh    时间: 2019-5-7 22:04
本帖最后由 eeyeh 于 2019-5-7 22:05 编辑
MinskyLee 发表于 2019-5-6 20:30
楼主,为什么我运行你的代码输出
model load done
rknn init done

我的是yolov3 416大小的, 所以模型转换的时候用的yolov3的weights, cfg中输入大小要改成416, 官方提供的python transform好像是608的, 可能是这个原因
作者: shopping    时间: 2019-10-15 12:11
本帖最后由 shopping 于 2019-10-15 12:13 编辑
momo 发表于 2019-4-24 11:06
这个版本在楼主的基础上修改的,支持多线程绑定CPU,支持摄像头和本地视频处理;两个大核处理NPU,其他小核 ...

你好,答主,问一下你发的那个 rknn_ssd_multi.cpp 里 int multi_npu_process_initialized[2] 干嘛用的,我看了一遍,感觉有它没它差不多。
  1. int multi_npu_process_initialized[2] = {0, 0};  // 定义

  2. <blockquote>while (true) {
复制代码

作者: wang64    时间: 2020-6-5 15:35
momo 发表于 2019-4-24 11:06
这个版本在楼主的基础上修改的,支持多线程绑定CPU,支持摄像头和本地视频处理;两个大核处理NPU,其他小核 ...

这个版本可以在android上编译吗
作者: online1    时间: 2020-9-17 18:06
请问,这个yolo的c++代码能在firefly的rk3399pro上面运行吗,还是必须在瑞芯微官方的rk3399pro上才能运行?
作者: brunolin    时间: 2020-9-23 16:39
online1 发表于 2020-9-17 18:06
请问,这个yolo的c++代码能在firefly的rk3399pro上面运行吗,还是必须在瑞芯微官方的rk3399pro上才能运行? ...

都可以運行
作者: geoergecyr    时间: 2020-11-5 22:50
momo 发表于 2019-4-24 11:06
这个版本在楼主的基础上修改的,支持多线程绑定CPU,支持摄像头和本地视频处理;两个大核处理NPU,其他小核 ...

您好,我用的是USB外接摄像头,使用yolov3-tiny模型,跑您的代码只有20FPS左右,我始终没有解决这个问题,期待您能回复。
作者: geoergecyr    时间: 2020-11-7 15:30
geoergecyr 发表于 2020-11-5 22:50
您好,我用的是USB外接摄像头,使用yolov3-tiny模型,跑您的代码只有20FPS左右,我始终没有解决这个问题 ...

我找到的原因是摄像头的最高帧率是30FPS,因此无法达到更高了。
作者: CQQQQQQQQQQ    时间: 2021-3-24 15:26
多谢分享,谢谢楼主和三楼的朋友
作者: CQQQQQQQQQQ    时间: 2021-4-1 09:45
用三楼的C++多线程代码,运行自己训练的yolov4-tiny.rknn模型,结果识别不了目标物体,但是使用python版本的代码可以准确识别,不知道哪里出了问题?API和DRV都是用的1.6.0版本的,求教各位大佬
作者: sunkai    时间: 2021-4-2 09:31
可以编译后在rv1126上运行吗
作者: sunkai    时间: 2021-4-6 14:07
你好,rknn-api里面的opencv好像不支持videocapture这个函数,你是怎么解决的,自行编译opencv吗
作者: sunkai    时间: 2021-4-6 14:08
geoergecyr 发表于 2020-11-7 15:30
我找到的原因是摄像头的最高帧率是30FPS,因此无法达到更高了。


你好,rknn-api里面的opencv好像不支持videocapture这个函数,你是怎么解决的,自行编译opencv吗
作者: czcl    时间: 2021-6-22 18:22
多谢,这个能够帮助我理解yolov的输出流程
作者: feiyang    时间: 2021-7-14 19:05
sunkai 发表于 2021-4-6 14:08
你好,rknn-api里面的opencv好像不支持videocapture这个函数,你是怎么解决的,自行编译opencv吗 ...

您好,我也碰到同样的问题, 请问你最终是怎么解决问题的呢,谢谢




欢迎光临 Toybrick (https://t.rock-chips.com/) Powered by Discuz! X3.3