人工智能
直播中

tinnu

8年用户 133经验值
擅长:可编程逻辑 嵌入式技术 控制/MCU
私信 关注

【瑞芯微RK1808计算棒试用体验】如何获取识别后的信息

上一篇关于在ARM上搭载环境的帖子莫名其妙没了,郁闷,不知道是不是因为用了友商的板子(哭),可是虚拟机真的没办法读摄像头啊……为此我双十一搞了台Deepin系统的笔记本专门测试。
DEEPIN是基于debain的,直接运行install_rknn_api.sh是会报错的,因此要用我修改过的脚本:
install_rknn_api.sh.zip (1.13 KB)
(下载次数: 0, 2019-11-17 22:36 上传)



工程文件:
ssd_demo_Qt_reset.zip (4.8 MB)
(下载次数: 0, 2019-11-17 22:37 上传)



下面就分析怎么如何获取识别后的信息:
(一)rknn_testdetect_img检测过程
几乎每一层封装都有一个与检测有关的函数,而距离我们用户最近的一层,无疑就是rknn_testdetect_img函数。
detect_img函数三个传入参数:
void *ctx, cv::Mat & img, struct rknn_out_data *out_data
第一个——无名指针,实际上是rknn_test类对象的指针,由于多线程中可能并不只初始化一个对象,因此用this指针是不安全的。
第二个——img,传入图像
第三个——out_data,输出的数据
函数执行
1-rknn_test类对象的指针付给要用的函数内的rknn_test *test_ctx
2-out_data清空
3-调用rknn_api(一个rknn类对象)的set_input函数把img及相关参数输入
4-调用rknn_apirun函数,运行
调用rknn_apiget_outputs_data函数,获取输出数据,并将之塞入传入结构体out_data
这里设计一个数据量的问题,这个数据量由test_ctx->num_outputtest_ctxrknn_test类对象,如1中描述),这个num_output是在以前的一个初始化函数里面,随着in_out_numrknn_input_output_num结构体,这个结构体里面只有两个32uint32_t对象被传进rknn_api(一个rknn类对象)里面。num_output就是一个32位对象,说到底,就是传输一些32位数据,后面才会对这些数据进行整理。
5-然后就没有然后了,数据都被传进out_data中,就要在show_img里面处理了

(二)rknn_testshow_img检测过程

1-rknn_test类对象的指针付给要用的函数内的rknn_test *test_ctx
2-调用一个post_process指针函数,这个指针函数实在main函数里面调用rknn_test类对象的run函数时传进来的并初始化的,也就是说,这是个main文件里面的函数。我找了下main文件,发现了:
int post_process(void *data, cv::Mat & img, float fps,
         struct rknn_out_data *out_data)

(三)post_process指针函数

结果都保存在out_data内。
通过decodeCenterSizeBoxes函数和nms函数,提取出一个predictions的浮点指针,里面保存的就是要画的框框的左下、右上点。
ssd->labels保存模型的标签,从out_data里面提取出预测标签的下标,从ssd->labels里面找它的名字来。

PS:题外话,我们看下这个结构体:
struct ssd_data {
    float boxPriors[4][NUM_RESULTS];
    string labels[91];
};
再看看rknn_test类里面调用post_process()的传入参数,是rknn_test类的user_data成员变量
这个结构体初始化的路径是:main(main.c)->run(rknn_test.c)->common_run(rknn_test.c)

(四)搞事情

所以,要想搞事情,就在post_process函数里面就行了,比如我们标示一下识别物体的中点,识别到之后停止程序:
1-为了识别之后停止,首先要考虑如何停止,最简单的方式就是把is_running=false。但是is_runningrknn-opencv对象的成员变量,还是私有的,它的传递情况如下:
Main->rknn_test->rknn_opencv
几乎每一个类都是局部变量,为了不产生大变动,我不得不在main里面加一个rknn_test的全局变量指针,在rknn_test里面加一个rknn_opencv的类指针,在rknn_opencv加一个可以修改is_running的执行函数,相当于一层一层地凿孔,从地表控制地下。
2-标识函数简单,不作详细说明:

  1. int JudgeDect(cv::Mat img, string label, int x1, int y1, int x2, int y2)
  2. {
  3.     if(label.find("cup")!=string::npos || label.find("bottle")!=string::npos){
  4.         int middle_x = (x1+x2)/2;
  5.         int middle_y = (y1+y2)/2;
  6.         cout << "(x,y):t(" << middle_x << "," << middle_y <<")"<
  7. //        counter++;
  8. //        obj.push_back(Point(x*frame.cols,y*frame.rows));
  9.         Mat t_imgDect;
  10.         img.copyTo(t_imgDect);
  11.         rectangle(t_imgDect, Point(middle_x-5, middle_y-5), Point(middle_x+5, middle_y+5),
  12.                   Scalar(255, 255, 255), CV_FILLED);
  13.         imshow("dect img", t_imgDect);
  14.         g_rknnTest->m_rknn_opencv_interface->setIsRunning();
  15.     }
  16. }








回帖(1)

小麦地

2020-2-26 12:23:36
楼主这个项目什么时候可以完工啊  期待
举报

更多回帖

发帖
×
20
完善资料,
赚取积分