关于整个demo工程如何构建,这里简单描述下自己的认识:
rknn_test:主要负责底层交互的,配置视频文件/摄像头、识别推进什么的都在rknn_test的类对象函数里面实现。
rknn_opencv:主要是负责开启多线程、多线程资源管理配置。因为很多函数指针存在,因此与rknn_test的耦合性变得很奇怪。
rknn:这个基本与我们用户屏蔽,目前阶段不太需要管
由于没有时间整理,这里贴一点当时阅读代码的笔记出来,供大家参考,可能内容会比较凌乱,以后有机会再仔细分析:
Ssd_demo:main入口
初始化rknn_test,这是个缺省函数,不会特殊地初始化任何变量,不需要关注
rknn_test::load_model 这个是加载ssd模型,没有涉及什么检测流程,不需要关注
rknn_test::set_input_info 这个是设置图形相关参数,没有涉及什么检测流程,不需要关注
rknn_test::run 这个是主要关注的
打开rknn_test.cpp
run里面主要调用了一个叫common_run的函数:
初始化一个rknn_opencv对象(在rknn_opencv.cpp),不是缺省函数,会对一些变量进行初始化。其中尤其值得注意的是idle_queue对象,这是个std::queue对象,有点像vector变量,可以通过push、pop压栈、出栈,但vector是先入后出,queue是先入先出,对图像流进行中转保存。
然后调用rknn_opencv::start函数,
被传入三个参数,这三个参数都是函数指针(是一个函数,以指针形式表示),
采用thread函数启动了两个线程,分别运行get_img_task、detect_img_task,返回值交给两个函数指针。
最后调用rknn_opencv::update_show函数,这个函数的作用是显示图像,由于图像显示需要有先后顺序,所以不能用子线程,必须while顺序执行
打开rknn_opencv.cpp
get_img_task
通过函数指针的方式调用了一次rknn_test.cpp里面的rknn_test::get_img,get_img这个函数会从图像数据流里面读取一次原始图像。get_img_task函数在子线程里面,会不停地调用get_img函数,获取图像。然后他又捣鼓了个input_queue,把图像装进去,原始图像流就是通过这个对象输出出去的。当然这个过程还设计一些多线程阻塞的操作。
detect_img_task
通过input_queue出栈,读个原始图像,再传入rknn_test::detect_img函数(通过上面提到的start函数里面的函数指针传递),进行识别。识别完成,把数据输出到output_queue
有一个bug,当视频流结束时,detect_img_task会把is_running置为false,在detect_img_task里面判断is_running为false,错误地停止了识别(此时input_queue还没搞定),结果到了 update_show函数时,因为is_running置为false,output_queue也空了(detect_img_task停止了,不识别了)所以就被意外结束了。
解决了上述问题后,发现只是末尾多了几帧,依然很多信息丢失,发现原来是idle_queue容量过小。
关于整个demo工程如何构建,这里简单描述下自己的认识:
rknn_test:主要负责底层交互的,配置视频文件/摄像头、识别推进什么的都在rknn_test的类对象函数里面实现。
rknn_opencv:主要是负责开启多线程、多线程资源管理配置。因为很多函数指针存在,因此与rknn_test的耦合性变得很奇怪。
rknn:这个基本与我们用户屏蔽,目前阶段不太需要管
由于没有时间整理,这里贴一点当时阅读代码的笔记出来,供大家参考,可能内容会比较凌乱,以后有机会再仔细分析:
Ssd_demo:main入口
初始化rknn_test,这是个缺省函数,不会特殊地初始化任何变量,不需要关注
rknn_test::load_model 这个是加载ssd模型,没有涉及什么检测流程,不需要关注
rknn_test::set_input_info 这个是设置图形相关参数,没有涉及什么检测流程,不需要关注
rknn_test::run 这个是主要关注的
打开rknn_test.cpp
run里面主要调用了一个叫common_run的函数:
初始化一个rknn_opencv对象(在rknn_opencv.cpp),不是缺省函数,会对一些变量进行初始化。其中尤其值得注意的是idle_queue对象,这是个std::queue对象,有点像vector变量,可以通过push、pop压栈、出栈,但vector是先入后出,queue是先入先出,对图像流进行中转保存。
然后调用rknn_opencv::start函数,
被传入三个参数,这三个参数都是函数指针(是一个函数,以指针形式表示),
采用thread函数启动了两个线程,分别运行get_img_task、detect_img_task,返回值交给两个函数指针。
最后调用rknn_opencv::update_show函数,这个函数的作用是显示图像,由于图像显示需要有先后顺序,所以不能用子线程,必须while顺序执行
打开rknn_opencv.cpp
get_img_task
通过函数指针的方式调用了一次rknn_test.cpp里面的rknn_test::get_img,get_img这个函数会从图像数据流里面读取一次原始图像。get_img_task函数在子线程里面,会不停地调用get_img函数,获取图像。然后他又捣鼓了个input_queue,把图像装进去,原始图像流就是通过这个对象输出出去的。当然这个过程还设计一些多线程阻塞的操作。
detect_img_task
通过input_queue出栈,读个原始图像,再传入rknn_test::detect_img函数(通过上面提到的start函数里面的函数指针传递),进行识别。识别完成,把数据输出到output_queue
有一个bug,当视频流结束时,detect_img_task会把is_running置为false,在detect_img_task里面判断is_running为false,错误地停止了识别(此时input_queue还没搞定),结果到了 update_show函数时,因为is_running置为false,output_queue也空了(detect_img_task停止了,不识别了)所以就被意外结束了。
解决了上述问题后,发现只是末尾多了几帧,依然很多信息丢失,发现原来是idle_queue容量过小。
1
举报