发 帖  
原厂入驻New
申请华秋企业认证 多层板首单免费打样!
30s提交资料,10分钟通过审核(免费赔付+顺丰包邮)>>立即报名

[经验] 【瑞芯微RK1808计算棒试用体验】PC端环境搭建与使用

2019-10-7 19:45:36  275 python OpenCV
分享
0
(一)搭建基于python+opencv的开发环境
实际上,作为C++开发者,这个环境是大概是不需要搭建的,因为RK1808C/C++语言的API,而且更加方便。但一开始被WIKI里面的快速上手糊弄了一把,还是捣鼓了一番。

首先,我使用的是ubuntu18.04系统+Oracle虚拟机,这个系统安装时候就默认带有python2.7 + python3.6,因此大部分python环境都不需要操心。但唯独安装opencv的时候遇上大问题。

我使用的是最新的opencv 3.4.7,从刚学opencv那会,正是3.1.0刚出来的时候,从那时起我就基本没碰过opencv2.x特性的编程,因此让我用apt安装2.4.13实在是忍不了。
1、下载opencv 3.4.7也是个不小的工程,我下了好久都中道崩殂,无奈只能找了个开源的下载器Free Download Manager 5(迅雷真的是算了),崩了一次,第二次下得飞快。
2cmake我采用cmake-gui的方式,因为这种方式更加直观,可以通过图形界面把大部分都配置好。不过在cmake的时候ippicv_2019_lnx_intel64_general_20180723.tgz无法下载,这个可以参考:
https://blog.csdn.net/orDream/article/details/84311697
3、遇到eigen头文件找不到的问题,参考:
https://www.cnblogs.com/newneul/p/8256803.html
  1. sudo cp -r /usr/include/eigen3/Eigen /usr/include
复制代码
4、最棘手的问题最后出现啦,因为rk1808的开发环境必须是python3.5以上,因此python2是不可行的,但cmake之后,出现:

  1. Python (for build):            /usr/bin/python2
复制代码

无论怎么修改配置都不行,网上有个PYTHON_DEFAULT选项可以配置python版本,但cmake里面没找到,需要在sh脚本里面使用。最终我绞尽脑汁,终于探索出一个方法:
python2的配置删掉!
opencv配置.png
如图,我把PYTHON2_EXECUTABLE清空之后,如愿出现

  1. Python (for build):            /usr/bin/python3
复制代码


(二)其他开发环境
除了python+opencv外,还需要安装RKNN-ToolkittensoRFlow,这个参考wiki即可,不赘述:
http://t.rock-chips.com/wiki.php?mod=view&pid=28

(三)搭建C++Mobilenet-ssd开发环境
1、下载npu_transfer_proxy:
http://repo.rock-chips.com/rk1808/npu_transfer_proxy/
2、下载C API:
http://repo.rock-chips.com/rk1808/rknn-api/
3、github下载mobilenet-ssd相关文件:
https://github.com/rockchip-toybrick/slave_mobilenet_ssd

相关教程见wiki:
http://t.rock-chips.com/wiki.php?mod=view&id=71

(三)虚拟机视频流问题
Oracle的虚拟机用不了摄像头是一直以来的老毛病了。我用windows拍了一段视频,放到虚拟机上代替摄像头。
我发现C API里面的run函数重载出两个,一个是用于摄像头,另一个是用于视频文件的,这就很省事了……我一开始是这么想的。
但事实上,直接改用用于视频文件的那个run函数,程序会出bug:视频只会识别一小段。
经过一天的努力,我终于勉强摸透了原理,这个demo有个缓存的机制,而读视频流的速度远远比识别的速度快,因为视频的长度是有限的,一旦读完,程序就认为已经结束,强制停止,不会把已经读进来,但没识别完的内容完成。但读摄像头的视频流是无限的,因此这个demo为摄像头设置是没问题的。
解决这个问题有两个方法:
1、给读视频加个延时,即在rknn_opencv.cpp文件的get_img_task函数的while循环里价格usleep(100000);延时100ms。
2、修改判断条件,使之读完视频流之后继续把未完成的部分识别完显示出来。并且增加缓存大小。
第二个方法比较啰嗦,而我下面附加的工程也是使用这种方法的,以后我发一贴详细讲解其中的缘由。这个方法比较第一个方法,优势主要在于可以识别得更快,第一个方法为了避免demo里面的bug,必须确保读取速度足够的慢,因此延时要非常保守(比较大),降低了识别速度。但第二个方法的弊端也很明显,他需要一个与视频长度成正比的缓存区,基本上要保证缓存大小和视频总帧数一致,对内存的要求比较苛刻了。

(四)Qt工程
我把整个项目集成进了一个Qt工程,对于阅读代码和入门来说比较方便,有兴趣可以下来看一下。
使用这个工程的前提当然是:
1、你已经安装了相应的环境
2、开启了npu_transfer_proxy守护进程
3、Qt的.pro文件里面的INCLUDEPATH和LIBS换成自己的opencv路径。
4、main.cpp文件的VIDEO_NODE改成自己的视频文件路径

没有经过修改,存在“只识别一半的bug”的工程:
ssd_demo_Qt.zip (5.68 MB, 下载次数: 0)

经过修改,可以识别9秒左右不出bug的工程:
ssd_demo_Qt_reset.zip (5.68 MB, 下载次数: 6)


至于usleep方式因为太过简单,有需要自己手动加一行代码即可

相关经验

tinnu 2019-10-7 19:51:52
识别效果如图,这是采用第二种方式排除bug的识别结果:
c++识别效果.gif
看起来可能有点卡,因为是gif,但实际上非常流畅……显示的fps在16帧左右
回复

举报

tinnu 2019-10-7 20:00:37
关于整个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变量,可以通过pushpop压栈、出栈,但vector是先入后出,queue是先入先出,对图像流进行中转保存。

然后调用rknn_opencv::start函数,
被传入三个参数,这三个参数都是函数指针(是一个函数,以指针形式表示),
采用thread函数启动了两个线程,分别运行get_img_taskdetect_img_task,返回值交给两个函数指针。

最后调用rknn_opencv::update_show函数,这个函数的作用是显示图像,由于图像显示需要有先后顺序,所以不能用子线程,必须while顺序执行
打开rknn_opencv.cpp
get_img_task
通过函数指针的方式调用了一次rknn_test.cpp里面的rknn_test::get_imgget_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_runningfalse,错误地停止了识别(此时input_queue还没搞定),结果到了 update_show函数时,因为is_running置为falseoutput_queue也空了(detect_img_task停止了,不识别了)所以就被意外结束了。

解决了上述问题后,发现只是末尾多了几帧,依然很多信息丢失,发现原来是idle_queue容量过小。


1 回复

举报

小萃米 2019-10-15 17:58:33
学习学习  这个计算棒好像还挺不错啊
回复

举报

只有小组成员才能发言,加入小组>>

143个成员聚集在这个小组

加入小组

创建小组步骤

关闭

站长推荐 上一条 /10 下一条

快速回复 返回顶部 返回列表