赞
踩
前两天写了ncnn的大致流程,感觉写的比较简单,这段时间查阅了些资料,下方会给出接见链接,方便阅读。
运行流程解析:
此处推荐:https://zhuanlan.zhihu.com/p/338121531
来加强自己对ncnn源码的理解。
1、图像预处理ncnn::Mat
NCNN对于我们给定的网络和输入,首先进行图像预处理,其基于[ncnn::Mat]的数据结构完成。
其中,from_pixels_resize() 这个函数的作用是生成目标尺寸大小的网络输入Mat,
它的实现在https://github.com/Tencent/ncnn/blob/b93775a27273618501a15a235355738cda102a38/src/mat_pixel.cpp#L2543。
它的内部实际上是「根据传入的输入图像的通道数」完成resize_bilinear_c1/c2/c3/4 即一通道/二通道/三通道/四通道 图像变形算法,可以看到使用的是双线性插值算法。
这些操作的实现在https://github.com/Tencent/ncnn/blob/master/src/mat_pixel_resize.cpp#L27。
然后经过Resize之后,需要将像素图像转换成ncnn::Mat。这里调用的是Mat::from_pixels()这个函数,它将我们Resize操作之后获得的像素图像数据(即float*数据)根据特定的输入类型赋值给ncnn::Mat。
2、模型解析ncnn::Net
文档中所有网络层的详细参数设置:
https://github.com/Tencent/ncnn/wiki/operation-param-weight-table
Net::load_param函数,首先会遍历param文件中的所有网络层,然后根据当前层的类型调用create_layer()/ net::create_custom_layer()来创建网络层,然后读取输入Blobs和输出Blobs和当前层绑定,再调用paramDict::load_param(fp)解析当前层的特定参数(参数字典),按照id=参数/参数数组来解析。最后,当前层调用layer->load_param(pd)载入解析得到的层特殊参数即获得当前层特有的参数。
3、网络运行 ncnn::Extractor
至此,我们将网络的结构和权重信息都放到了ncnn::Net这个结构中,接下来我们就可以新建网络提取器 Extractor Net::create_extractor,它给我们提供了设置网络输入(Extractor::input),获取网络输出(Extractor::extract),设置网络运行线程参数(Extractor::set_num_threads)等接口。接下来,我们只需要调用Extractor::extract运行网络(net)的前向传播函数net->forward_layer就可以获得最后的结果了。
另外,ncnn::Extractor还可以设置一个轻模式省内存 即set_light_mode(true),原理是net中每个layer都会产生blob,除了最后的结果和多分支中间结果,大部分blob都不值得保留,开启轻模式可以在运算后自动回收,省下内存。但需要注意的是,一旦开启这个模式,我们就不能获得中间层的特征值了,因为中间层的内存在获得最终结果之前都被回收掉了。例如:「某网络结构为 A -> B -> C,在轻模式下,向ncnn索要C结果时,A结果会在运算B时自动回收,而B结果会在运算C时自动回收,最后只保留C结果,后面再需要C结果会直接获得,满足大多数深度网络的使用方式」。
资料推荐:
https://github.com/Tencent/ncnn/wiki (官方wiki文档,推荐)
ncnn::mat和cv::mat互转(非常详细):
https://github.com/Tencent/ncnn/wiki/use-ncnn-with-opencv
ncnn::Mat转cv::Mat:
https://www.codeleading.com/article/43032782351/
cv::Mat 二进制bin文件 cv:Mat转换:
https://blog.csdn.net/a1194110603/article/details/121970027
1、cv::Mat(float型)存为二进制bin文件:
ios::binary -> 以二进制模式打开文件
ios::trunc -> 覆盖存在的文件
遍历上文中矩阵m中的值并输出:
赞
踩
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。