Python API使用

安装

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

MNN

MNNTools

MNNTools提供目前主要是2个工具,用法可以参考mnnconvertmnnquant

使用Python Module API

数据类型

Python中的Module API与C++中的函数名略有区别,用法相似。主要数据类型如下:

推理流程

基本推理流程如下:

  • 创建Module

  • 创建输入: 使用exprnumpy函数创建Var即可作为输入

  • 执行推理

  • 获取输出: 输出为Var类型,可以通过exprnumpy函数执行后处理

示例

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)

其他示例可以参考示例;也可以参考示例工程

使用cv/numpy API

数据类型

Python的cvnumpy接口,其中cv是对C++中tools/cv实现的封装;numpy则是对expr接口的封装;这两个接口主要为了提高MNN的易用性,与opencvnumpy做到了再接口上的部分兼容,在用法和思路上基本一致。主要数据类型如下:

  • Var cv中的图像,numpy中的ndarray

主要用法

cvnumpy主要用作模型的前后处理部分,和一些数值计算任务。比如从图片直接读取数据后一般需要执行颜色空间变换,数据类型变换,缩放,裁剪等操作,这些可以用cv模块函数实现;模型输出的结果可能需要做一些额外的变换和计算,这些可以用numpy模块函数实现。

示例

使用cvnumpy中的函数做前后处理,执行模型推理的例子

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能力列表

cv模块提供了与OpenCV相似的接口函数,具备基础的图像处理能力,目前支持的cv函数60个。

图像编解码

函数名 功能
haveImageReader 是否可读(解码)
haveImageWriter 是否可写(编码)
imdecode 从内存解码为Mat
imencode 编码Mat到内存中
imread 读图片
imwrite 写图片

图像滤波

函数名 功能
blur 均值滤波,平滑模糊
boxFilter 盒子滤波,
dilate 膨胀
filter2D 2d卷积
GaussianBlur 高斯模糊
getDerivKernels 求导数,实际为Sobel/Scharr
getGaborKernel 获取Gabor核
getGaussianKernel 获得高斯核
getStructuringElement 获取结构化元素用于形态学操作
Laplacian 边缘检测滤波
pyrDown 高斯平滑+下采样
pyrUp 上采样+高斯平滑
Scharr 边缘检测滤波
sepFilter2D 2个一维kernel做滤波
Sobel 边缘检测滤波
spatialGradient 梯度,实际为Sobel
sqrBoxFilter 平方后滤波

图像形变

函数名 功能
getAffineTransform 仿射变换
getPerspectiveTransform 透视变换
getRectSubPix 截取矩形区域
getRotationMatrix2D 旋转矩阵
invertAffineTransform 仿射变换矩阵求逆
resize 图片放缩
warpAffine 仿射变换
warpPerspective 透视变换

图像转换

函数名 功能
blendLinear 线性混合2个图像
threshold 逐像素阈值化

绘画函数

函数名 功能
arrowedLine 画箭头
circle 画圆
drawContours 画轮廓
fillPoly 填充多边形
line 画线段
rectangle 画正方向

色彩空间转换

函数名 功能
cvtColor 颜色空间转换
cvtColorTwoPlane YUV420到RGB的转换

结构函数

函数名 功能
findContours 轮廓检测
contourArea 计算轮廓的面积
convexHull 计算点集的凸包
minAreaRect 最小外接矩形
boundingRect 计算点集的最小外接矩形
connectedComponentsWithStats 计算图像的连通域
boxPoints 计算矩形的四个顶点坐标

直方图

函数名 功能
calcHist 计算直方图

3D

函数名 功能
Rodrigues 旋转矩阵转换为旋转向量
solvePnP 计算2d到3d的映射

数组操作函数

函数名 功能
copyTo 带mask的拷贝
bitwise_and 带mask按位与
bitwise_or 带mask按位或
bitwise_xor 带mask按位异或
hconcat 水平方向拼接
vconcat 垂直方向拼接
mean 求均值
flip 翻转
rotate 旋转

numpy能力列表

numpy函数170个,函数列表如下:

数组创建

函数名 功能
empty 空数组
empty_like 空数组like
eye 对角线2d数组
identity 对角线2d数组
ones 全1数组
ones_like 全1数组like
zeros 全0数组
zeros_like 全0数组like
full 填充
full_like 填充like
array 创建数组
asarray 创建数组
asanyarray 创建数组
ascontiguousarray 创建数组
asmatrix 创建2d数组
copy 拷贝数组
arange 范围创建
linspace 区间创建
logspace log区间创建
geomspace log区间创建
meshgrid 坐标矩阵
mat 矩阵

数组操作

函数名 功能
copyto 拷贝至
shape 获取形状
reshape 改变形状
ravel 拉平
flat 拉平
flatten 拉平
moveaxis 移动维度
rollaxis 轮转维度
swapaxes 交换维度
T 转置
transpose 转置
atleast_1d 至少1维
atleast_2d 至少2维
atleast_3d 至少3维
broadcast_to 广播
broadcast_arrays 数组广播
expand_dims 增加维度
squeeze 压缩1维度
asfarray 转浮点
asscalar 转标量
concatenate 连接
stack 连接
vstack 垂直连接
hstack 水平连接
dstack 深度连接
column_stack 列连接
row_stack 行连接
split 切分
array_split 数组切分
dsplit 深度切分
hsplit 水平切分
vsplit 垂直切分
tile 重复堆叠
repeat 重复
reshape 变形

坐标操作

函数名 功能
nonzero 非0元素坐标
where 条件选取
unravel_index 反拉平坐标

线性代数

函数名 功能
dot 点乘
vdot 点乘
inner 内积
matmul 矩阵乘

逻辑函数

函数名 功能
all 全部非0
any 任意非0
logical_and
logical_or
logical_not
logical_xor 异或
array_equal 相等
array_equiv 相等
greater 大于
greater_equal 大于等于
less 小于
less_equal 小于等于
equal 等于
not_equal 不等

数学函数

API 功能
sin 正弦
cos 余弦
tan 正切
arcsin 反正弦
arccos 反余弦
arctan 反正切
hypot
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 取小

数组扩充

函数名 功能
pad 扩充

随机采样

函数名 功能
random 随机数
rand 随机数
randn 随机数
randint 随机定点数

排序,搜索,计数

函数名 功能
sortlexsortargsort 排序
argmax 最大值坐标
nanargmax 最大值坐标
argmin 最小值坐标
nanargmin 最小值坐标
argwhere 非0坐标
flatnonzero 非0元素
count_nonzero 非0总数

统计

函数名 功能
amin 最小值
amax 最大值
nanmin 最小值
nanmax 最大值
ptp 范围
average 均值
mean 均值
std 标准差
var 方差
nanmean 均值
nanstd 标准差
nanvar 方差