Firefly开源社区

NCC S1 SDK示例源码梳理及修改 - 支持图片直接分类和显示

572

积分

1

威望

0

贡献

社区版主

Rank: 7Rank: 7Rank: 7

积分
572
发表于 2018-11-30 16:12:05     
本帖最后由 rany 于 2018-11-30 16:12 编辑

简介
NCC S1是firefly发布的一款搭载GTI 2801s芯片的神经网络计算卡。其资料中包含一个SDK v3-1-2a和简单的示例代码。示例代码的功能为分类一张图片,但图片需要先通过image_tool转换,其运行时需要设置GTISDKPATH环境变量,通过shell打印分类的结果,其支持的模型为GNet1。示例代码总体来说使用不方便,展现结果也并不直观,现在由我来对示例代码进行简单的梳理和修改,通过OpenCV把图片转换的功能集成到示例程序中,同时通过显示图片和标签的方式展现分类的结果。

本文需要用到的物品或设备如下:  
    1. 烧写带有NCC S1驱动的Ubuntu的ROC-rk3399-PC板子一块  
    2. NCC S1神经网络计算卡一块  
    3. 支持HDMI的显示器  
    4. 鼠标键盘  
    5. 电源  

预备知识:  
    1. 对CNN(卷积神经网络)有基本了解  
    2. 有C++开发基础  

示例源码文件及结构
代码文件
示例代码的功能简单,源码文件不多,其结构如下:  
dir_structure.png

Classify.cpp和Classify.hpp为GNet1 FC(fully connected layers,全连接层)部分实现代码,负责加载FC_Model文件和完成分类。  
GNUmakefile与普通的makefile文件一样。  
GtiClassify.h为Classify类封装函数头文件,实现在Classify.cpp中。  
liteSample.cpp和liteSample.hpp为主程序源码。  
stdafx.h windows使用,可以忽略。  
本次主要修改liteSample.cpp、liteSample.hpp和GNUmakefile其它文件可不用修改。

示例代码流程图
在进行修改前先了解一下示例代码的基本执行流程,如下流程图。
flow.png

GtiDeviceCreate()、GtiOpenDevice()和GtiInitialization()三个函数功能分别为创建,打开和初始化GtiDevice设备,是使用SDK的基本流程。
GtiClassifyCreate()实际为new一个Classify对象,载入FC_Model和label文件。
GtiHandleOneFrameFloat()将图片传送到GTI 2801S中进行卷积运算,同时获取运算结果。  
GtiClassifyFC()处理GtiHandleOneFrameFloat()返回的结果。这里提一下GNet1在推理的过程中分两部分进行处理:一部分传入GTI 2801S中进行卷积运算,另一部分3个FC层和softMax在CPU中进行处理,GtiClassifyFC()即为进行GNet1后半部分处理过程。
GetPredicationString()功能为获取分类结果。
GtiClassifyRelease()功能为释放Classify对象。

源码修改
1. 设置默认GTISDKPATH
示例代码中的源码默认需要设置GTISDKPATH环境变量,其源码如下:
gti_sdk_path.png

将此处源码修改为:  
gti_sdk_path_m.png

修改此处之后在示例代码目录下执行sudo ./liteSample即可运行示例程序不需要切换到root用户。

2. 修改源码支持图片直接输入
GTI SDK支持的图片输入大小为224x224x3,即宽和高为224,颜色通道为3的图片,为提高运行效率图片需要先经过转换处理。查看SDK Tools目录下的图片转换工具image_tool中的gtiConvtImage2BGR_plannar.py源码:
image_tool.png
其通过OpenCV载入图片,然后将图片进行缩放处理,最后将图片的三个颜色通道按蓝,绿,红写入文件中。  示例程序中读取由image_tool转换后的图片的源码如下:
read_picture.png
232-239行先判断文件大小是否符合要求,如果符合要求则在243行中读取图片到m_Img224x224x3Buffer中,否则退出程序。修改图中的源码为image_tool的源码逻辑即可实现示例程序不通过image_tool转换直接分类任意图片。
修改后的源码如下:  
read_picture_m.png
此源码通过OpenCV读取和处理图片,将处理结果存放到m_Img224x224x3Buffer中,image和targetImage类型为cv::Mat。其逻辑与image_tool差不多。
将liteSample.cpp第40行中的bridge.bin改为bridge.jpg使程序默认加载jpg图片防止出错。

3. 显示分类结果
通过上面的修改,程序已经支持任意图片的输入,接下来修改源码使程序显示图片和在图片左上角显示分类结果。
首先在LiteSamples类中添加如下定义:
show_image_define.png
同时在liteSample.hpp中包含“opencv2/opencv.hpp”和“opencv2/opencv_modules.hpp”头文件。
然后在liteSample.cpp的void LiteSamples::Test_picture()函数下添加以下函数实现:
show_image.png
setLabel函数负责将分类的结果绘制到图片中,第270行获取显示文字的大小,第271-273行为绘制一个方形背景和文字。
showImage函数功能为设置显示窗口(280-282行)、调用setLabel设置标签(284行)和显示图片(285行),使用的函数基本来自OpenCV。  
最后修改输出结果部分代码,原代码如下:  
get_predication.png
第257-261行为获取相似率高的前五个结果,并输出。
现修改如下:  
get_predication_m.png
修改后的代码在输出前五个结果后,获取相似率最高的结果,调用showImage函数进行显示。删除原代码的264-265行。
至此显示图片部分修改完成。  

4. 最终修改及结果
最后修改GNUmakefile链接OpenCV,在GNUmakefile第61行下面添加如下代码:  
  1. LIBS += -lopencv_core -lopencv_highgui -lopencv_imgproc
复制代码
编译后运行结果如下:  
result.jpeg


回复

使用道具 举报

38

积分

0

威望

0

贡献

技术小白

积分
38
发表于 2018-11-30 21:26:31     
本帖最后由 cysin 于 2018-11-30 21:30 编辑

要是只能跑这几个模型,实在是没有什么实际意义。希望能开放底层接口,等着官方更新还不知道要到什么时候
回复

使用道具 举报

572

积分

1

威望

0

贡献

社区版主

Rank: 7Rank: 7Rank: 7

积分
572
发表于 2018-12-3 09:36:35     
cysin 发表于 2018-11-30 21:26
要是只能跑这几个模型,实在是没有什么实际意义。希望能开放底层接口,等着官方更新还不知道要到什么时候

你好,如果想添加新的模型支持可以参考PLAI已支持网络模型的实现。SDK中的库主要是NPU的驱动而已。
回复

使用道具 举报

30

积分

0

威望

0

贡献

技术小白

积分
30
发表于 2018-12-4 14:33:59     
rany 发表于 2018-12-3 09:36
你好,如果想添加新的模型支持可以参考PLAI已支持网络模型的实现。SDK中的库主要是NPU的驱动而已。

PLAI的相关资源在哪里获取?如何根据自己的需求更改网络参数
回复

使用道具 举报

572

积分

1

威望

0

贡献

社区版主

Rank: 7Rank: 7Rank: 7

积分
572
发表于 2018-12-4 17:17:32     
voidmain 发表于 2018-12-4 14:33
PLAI的相关资源在哪里获取?如何根据自己的需求更改网络参数

PLAI部分资料可以查看http://wiki.t-firefly.com/NCCS1/plai.html
回复

使用道具 举报

*滑块验证:
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

友情链接 : 爱板网 电子发烧友论坛 云汉电子社区 粤ICP备14022046号-2
快速回复 返回顶部 返回列表