MNN Python API可以使用源码安装 ,也可以直接使用pip
安装预编译whl包;pip
安装用法如下:
# 外部版本安装
pip install MNN==$version
# 公司内部版本安装
pip install -i https://artifacts.antgroup-inc.cn/simple/ MNN-Internal==$version
MNN在C++的基础上,增加了Python扩展。扩展单元包括两个部分:
MNN:负责推理,训练,图像处理和数值计算
MNNTools:对MNN的部分工具进行封装,包括:mnn,mnnconvert和mnnquant
MNN
MNNTools提供目前主要是2个工具,用法可以参考mnnconvert 和mnnquant
Python中的Module API
与C++中的函数名略有区别,用法相似。主要数据类型如下:
基本推理流程如下:
创建Module
创建输入: 使用expr
或numpy
函数创建Var
即可作为输入
执行推理
获取输出: 输出为Var
类型,可以通过expr
或numpy
函数执行后处理
import MNN .nn as nn
import MNN .cv as cv
import MNN .numpy as np
import MNN .expr as expr
# 配置执行后端,线程数,精度等信息;key-vlaue请查看API介绍
config = {}
config ['precision' ] = 'low' # 当硬件支持(armv8.2)时使用fp16推理
config ['backend' ] = 0 # CPU
config ['numThread' ] = 4 # 线程数
rt = nn .create_runtime_manager ((config ,))
# 加载模型创建_Module
net = nn .load_module_from_file ('mobilenet_v1.mnn' , ['data' ], ['prob' ], runtime_manager = rt )
# 读取图片
image = cv .imread ('cat.jpg' )
# 转换为float32, 形状为[224,224,3]
image = cv .resize (image , (224 , 224 ), mean = [103.94 , 116.78 , 123.68 ], norm = [0.017 , 0.017 , 0.017 ])
# 增加batch HWC to NHWC
input_var = np .expand_dims (image , 0 )
# NHWC to NC4HW4
input_var = expr .convert (input_var , expr .NC4HW4 )
# 执行推理
output_var = net .forward (input_var )
# NC4HW4 to NHWC
output_var = expr .convert (output_var , expr .NHWC )
# 打印出分类结果, 282为猫
print ("output belong to class: {}" .format (np .argmax (output_var )))
# output belong to class: 282
其他示例可以参考示例 ;也可以参考示例工程 。
使用Python Session API [deprecated]
不建议使用该API执行推理,建议使用Module API
Python中Session API
的函数名与用法与C++基本一样。使用的主要数据类型如下:
基本推理流程如下:
import MNN
import MNN .cv as cv
import MNN .numpy as np
import MNN .expr as expr
# 创建interpreter
interpreter = MNN .Interpreter ("mobilenet_v1.mnn" )
# 创建session
config = {}
config ['precision' ] = 'low'
config ['backend' ] = 'CPU'
config ['thread' ] = 4
session = interpreter .createSession (config )
# 获取会话的输入输出
input_tensor = interpreter .getSessionInput (session )
output_tensor = interpreter .getSessionOutput (session )
# 读取图片
image = cv .imread ('cat.jpg' )
dst_height = dst_width = 224
# 使用ImageProcess处理第一张图片,将图片转换为转换为size=(224, 224), dtype=float32,并赋值给input_data1
image_processer = MNN .CVImageProcess ({'sourceFormat' : MNN .CV_ImageFormat_BGR ,
'destFormat' : MNN .CV_ImageFormat_BGR ,
'mean' : (103.94 , 116.78 , 123.68 , 0.0 ),
'filterType' : MNN .CV_Filter_BILINEAL ,
'normal' : (0.017 , 0.017 , 0.017 , 0.0 )})
image_data = image .ptr
src_height , src_width , channel = image .shape
input_data1 = MNN .Tensor ((1 , dst_height , dst_width , channel ), MNN .Halide_Type_Float , MNN .Tensor_DimensionType_Tensorflow )
#设置图像变换矩阵
matrix = MNN .CVMatrix ()
x_scale = src_width / dst_width
y_scale = src_height / dst_height
matrix .setScale (x_scale , y_scale )
image_processer .setMatrix (matrix )
image_processer .convert (image_data , src_width , src_height , 0 , input_data1 )
# 使用cv模块处理第二张图片,将图片转换为转换为size=(224, 224), dtype=float32,并赋值给input_data2
image = cv .imread ('TestMe.jpg' )
image = cv .resize (image , (224 , 224 ), mean = [103.94 , 116.78 , 123.68 ], norm = [0.017 , 0.017 , 0.017 ])
input_data2 = np .expand_dims (image , 0 ) # [224, 224, 3] -> [1, 224, 224, 3]
# 合并2张图片到,并赋值给input_data
input_data1 = expr .const (input_data1 .getHost (), input_data1 .getShape (), expr .NHWC ) # Tensor -> Var
input_data = np .concatenate ([input_data1 , input_data2 ]) # [2, 224, 224, 3]
input_data = MNN .Tensor (input_data ) # Var -> Tensor
# 演示多张图片输入,所以将输入resize到[2, 3, 224, 224]
interpreter .resizeTensor (input_tensor , (2 , 3 , 224 , 224 ))
# 重新计算形状分配内存
interpreter .resizeSession (session )
# 拷贝数据到输入Tensor
input_tensor .copyFrom (input_data )
# 执行会话推理
interpreter .runSession (session )
# 从输出Tensor拷贝出数据
output_data = MNN .Tensor (output_tensor .getShape (), MNN .Halide_Type_Float , MNN .Tensor_DimensionType_Caffe )
output_tensor .copyToHostTensor (output_data )
# 打印出分类结果: 282为猫,385为象
output_var = expr .const (output_data .getHost (), [2 , 1001 ])
print ("output belong to class: {}" .format (np .argmax (output_var , 1 )))
# output belong to class: array([282, 385], dtype=int32)
其他示例可以参考示例 ;也可以参考示例工程 。
Python的cv
和numpy
接口,其中cv
是对C++中tools/cv
实现的封装;numpy
则是对expr
接口的封装;这两个接口主要为了提高MNN的易用性,与opencv
与numpy
做到了再接口上的部分兼容,在用法和思路上基本一致。主要数据类型如下:
Var cv
中的图像,numpy
中的ndarray
cv
和numpy
主要用作模型的前后处理部分,和一些数值计算任务。比如从图片直接读取数据后一般需要执行颜色空间变换,数据类型变换,缩放,裁剪等操作,这些可以用cv
模块函数实现;模型输出的结果可能需要做一些额外的变换和计算,这些可以用numpy
模块函数实现。
使用cv
与numpy
中的函数做前后处理,执行模型推理的例子
import MNN
import MNN .cv as cv
import MNN .numpy as np
# 加载模型
net = MNN .nn .load_module_from_file ('mobilenet_v1.mnn' , ["data" ], ["prob" ])
# cv模块图片处理
image = cv .imread ('cat.jpg' )
image = cv .resize (image , (224 , 224 ))
# 类似ndarray的数值运算
image = image - (103.94 , 116.78 , 123.68 )
image = image * (0.017 , 0.017 , 0.017 )
input_var = np .expand_dims (image , 0 )
input_var = MNN .expr .convert (input_var , MNN .expr .NC4HW4 )
output_var = net .forward (input_var )
output_var = MNN .expr .convert (output_var , MNN .expr .NHWC )
# 类似numpy操作的后处理
print ("output belong to class: {}" .format (np .argmax (output_var )))
其他示例可以参考示例 ;也可以参考示例工程 。
cv模块提供了与OpenCV相似的接口函数,具备基础的图像处理能力,目前支持的cv函数60个。
numpy函数170个,函数列表如下:
|
| arctan2 |
|
| sinh |
|
| cosh |
|
| tanh |
|
| arcsinh |
|
| arccosh |
|
| arctanh |
|
| around |
|
| round_ |
|
| rint |
|
| floor |
|
| ceil |
|
| trunc |
|
| prod | 积 |
| sum | 和 |
| nanprod | 积 |
| nansum | 和 |
| exp | e指数 |
| expm1 | e指数-1 |
| exp2 | 2指数 |
| log | 对数 |
| log10 | 10对数 |
| log2 | 2对数 |
| log1p | x+1对数 |
| logaddexp | exp对数 |
| logaddexp2 | 2指数对数 |
| sinc | |
| signbit | |
| copysign | |
| frexp | |
| ldexp | |
| add | 加 |
| reciprocal | 倒数 |
| positive | 取正 |
| negative | 取负 |
| multiply | 乘 |
| divide | 除 |
| power | 指数 |
| subtract | 减 |
| true_divide | 除 |
| floor_divide | 除 |
| float_power | 指数 |
| fmod | 模 |
| mod | 模 |
| modf | 模 |
| remainder | 余 |
| divmod | 除,余 |
| convolve | 卷积 |
| clip | 缩小范围 |
| sqrt | 平方根 |
| cbrt | 立方根 |
| square | 平方 |
| absolute | 绝对值 |
| fabs | 绝对值 |
| sign | 符号 |
| maximum | 取大 |
| minimum | 取小 |
| fmax | 取大 |
| fmin | 取小 |
函数名
功能
random
随机数
rand
随机数
randn
随机数
randint
随机定点数