将yolov8部署到安卓——前言
笔者之前接触到的各种深度学习网络(其实好像只有yolo)都是一整个python的项目文件。而怎么把yolo之类的算法部署到各种平台上一无所知。首先,不管是yolo还是其他深度学习算法,它们首先是算法,而不是python文件,也就是说他们本质上是一种神经网络,是一种输入一个东西(视频或者图片或者文本),然后用输入的数据进行一系列的运算,最后得到一组输出的数字的东西。至于其他像是检测框还有前端页面都是建立在这个网络的基础之上的。而我们所要做的就是用各种编程语言,把这些数学运算过程表示出来,所以理论上任何的编程语言都可以实现神经网络,而深度学习框架就是用各种语言实现的,能够更好的辅助完成这些计算的东西,类似一个个小型的计算器。而Python非常擅长实现这些运算,所以现在的深度学习框架大多与Python相关。
如上所述,神经网络就是执行一系列特殊运算的东西,而神经网络的各个层结构则是为了方便描述而人为定义出来的,所以只要我们能够用数据把神经网络的结构和参数给记录下来,那么我们就拥有了一个神经网络,只需要用这些数据就可以构建出神经网络了。但是我们所熟知的各种深度学习框架如TensorFlow、Pytorch等大多是训练框架,也就是说它们主要是用来训练得到神经网络的参数和结构的,而不是使用神经网络。因此,对于移动设备这种算力不强的平台,我们就需要对神经网络的推导过程做专门的优化。于是就有人针对特定的平台用相应的语言开发针对神经网络推导过程优化的框架,也就是用其他的语言把那些和推导相关的小的计算器重新写一遍,让它们适应新平台的特性,这就是模型推理部署框架。可以参考https://www.zhihu.com/question/329372124
所以我们需要做的事情就是选择一个支持我们目标平台的框架,把原始框架下描述的神经网络提供给它,让它把提供的模型转换成自己描述下的模型,然后再根据这个模型来进行推导。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29
| 7767517 # 文件头 魔数 75 83 # 层数量 输入输出blob数量 # 下面有75行 Input data 0 1 data 0=227 1=227 2=3 Convolution conv1 1 1 data conv1 0=64 1=3 2=1 3=2 4=0 5=1 6=1728 ReLU relu_conv1 1 1 conv1 conv1_relu_conv1 0=0.000000 Pooling pool1 1 1 conv1_relu_conv1 pool1 0=0 1=3 2=2 3=0 4=0 Convolution fire2/squeeze1x1 1 1 pool1 fire2/squeeze1x1 0=16 1=1 2=1 3=1 4=0 5=1 6=1024 ... 层类型 层名字 输入blob数量 输出blob数量 输入blob名字 输出blob名字 参数字典
参数字典,每一层的意义不一样: 数据输入层 Input data 0 1 data 0=227 1=227 2=3 图像宽度×图像高度×通道数量 卷积层 Convolution ... 0=64 1=3 2=1 3=2 4=0 5=1 6=1728 0输出通道数 num_output() ; 1卷积核尺寸 kernel_size(); 2空洞卷积参数 dilation(); 3卷积步长 stride(); 4卷积填充pad_size(); 5卷积偏置有无bias_term(); 6卷积核参数数量 weight_blob.data_size(); C_OUT * C_in * W_h * W_w = 64*3*3*3 = 1728 池化层 Pooling 0=0 1=3 2=2 3=0 4=0 0池化方式:最大值、均值、随机 1池化核大小 kernel_size(); 2池化核步长 stride(); 3池化核填充 pad(); 4是否为全局池化 global_pooling(); 激活层 ReLU 0=0.000000 下限阈值 negative_slope(); ReLU6 0=0.000000 1=6.000000 上下限
综合示例: 0=1 1=2.5 -23303=2,2.0,3.0
数组关键字 : -23300 -(-23303) - 23300 = 3 表示该参数在参数数组中的index 后面的第一个参数表示数组元素数量,2表示包含两个元素
|
我的目标平台是安卓,所以选择了腾讯的ncnn框架,其实国内互联网三巨头都有自己的框架,但是ncnn是名气最大的(似乎),也是性能最好的(自称)。至于安卓平台的开发环境,我选择了QT,因为Java我并不熟悉(其实C++也是……)。
官方示例
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29
| #include <opencv2/core/core.hpp> #include <opencv2/highgui/highgui.hpp> #include "net.h"
int main() { cv::Mat img = cv::imread("image.ppm", CV_LOAD_IMAGE_GRAYSCALE); int w = img.cols; int h = img.rows;
ncnn::Mat in = ncnn::Mat::from_pixels_resize(img.data, ncnn::Mat::PIXEL_GRAY, w, h, 60, 60); float mean[1] = { 128.f }; float norm[1] = { 1/128.f }; in.substract_mean_normalize(mean, norm);
ncnn::Net net; net.load_param("model.param"); net.load_model("model.bin");
ncnn::Extractor ex = net.create_extractor();
ex.input("data", in);
ncnn::Mat feat; ex.extract("output", feat);
return 0; }
|