Back to Mnn

Python API使用

docs/inference/python.md

3.5.032.7 KB
Original Source

Python API使用

安装

MNN Python API可以使用源码安装,也可以直接使用pip安装预编译whl包;pip安装用法如下:

bash
# 外部版本安装
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函数执行后处理

示例

python
import MNN.nn as nn
import MNN.cv as cv
import MNN.numpy as np
import MNN.expr as expr

# 配置执行后端,线程数,精度等信息;key-value请查看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++基本一样。使用的主要数据类型如下:

推理流程

基本推理流程如下:

示例

python
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中的函数做前后处理,执行模型推理的例子

python
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膨胀
filter2D2d卷积
GaussianBlur高斯模糊
getDerivKernels求导数,实际为Sobel/Scharr
getGaborKernel获取Gabor核
getGaussianKernel获得高斯核
getStructuringElement获取结构化元素用于形态学操作
Laplacian边缘检测滤波
pyrDown高斯平滑+下采样
pyrUp上采样+高斯平滑
Scharr边缘检测滤波
sepFilter2D2个一维kernel做滤波
Sobel边缘检测滤波
spatialGradient梯度,实际为Sobel
sqrBoxFilter平方后滤波

图像形变

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

图像转换

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

绘画函数

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

色彩空间转换

函数名功能
cvtColor颜色空间转换
cvtColorTwoPlaneYUV420到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区间创建
logspacelog区间创建
geomspacelog区间创建
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
expe指数
expm1e指数-1
exp22指数
log对数
log1010对数
log22对数
log1px+1对数
logaddexpexp对数
logaddexp22指数对数
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方差