依赖:安装Tesnsorflow 2.0、安装Python3.7以上、安装VSCode、Windows操作系统
创建VSCode项目目录,并打开文件夹
--model_4
--model.h5
--model.json
--main.py
根据文件加载json模型和weight数据
import os
from tensorflow import keras
import tensorflow as tf
import numpy as np
class Model:
def __init__(self, load_quantize=False):
keras.backend.set_learning_phase(0)
self.__load_model()
def __load_model(self, dir="model_4"):
with open(os.path.join(dir, "model.json"), "r") as f:
loaded_model_json = f.read()
#装载模型数据
self.model = keras.models.model_from_json(loaded_model_json)
#装载模型训练参数
self.model.load_weights(os.path.join(dir, "model.h5"))
def __compile_model(self):
self.model.compile(optimizer=keras.optimizers.Adam(),
loss=keras.losses.categorical_crossentropy,
metrics=["accuracy"])
转储模型
import tensorflow as tf
model = Model()
tf.saved_model.save(model.model, "onnx_model")
pip install tf2onnx
python -m tf2onnx.convert --saved-model football_player_classific_model --output "model.onnx"
下载Netron并默认安装
https://github.com/lutzroeder/netron/releases/tag/v6.2.3
打开模型文件,查看首个input
如:input_11
安装机器学习运行时Nuget
Microsoft.ML.OnnxRuntime
安装OpenCV包及依赖
OpenCvSharp4
OpenCvSharp4.Extensions
OpenCvSharp4.runtime.win
Numpy.Bare
基础扩展函数
///
/// 张量转换
///
///
///
public static DenseTensor<float> ToDenseTensor(this NDarray darray,int size = 80)
{
var memory = darray.astype(np.float32).GetData<float>();
var inputTensor = new DenseTensor<float>(memory, darray.shape.Dimensions);
return inputTensor;
}
///
/// MatToNDarray(RGB转换)
///
///
///
public static NDarray ToNDarray(this Mat frameMat)
{
var newimage = frameMat.Reshape(1);
newimage.GetArray(out byte[] imageArray);
var array = Numpy.np.array(imageArray, dtype: np.uint8).reshape(frameMat.Rows, frameMat.Cols, frameMat.Channels());
array = np.expand_dims(array, 0);
return array;
}
基础图像加载函数
public class LoadImages
{
public static Mat Load(string file)
{
var basepath = AppDomain.CurrentDomain.BaseDirectory;
var fileFullPath = Path.Combine(basepath, "Assets", file);
var filemat = Cv2.ImRead(fileFullPath);
return filemat;
}
public static IEnumerable<Mat> LoadVideo(string file)
{
Mat imageOriginal = new Mat();
using (var videocapture = new VideoCapture(file))
{
while (videocapture.Read(imageOriginal))
yield return imageOriginal;
}
}
}
模型应用函数(类
public class ClassificWithOnnx
{
///
/// 预测(推理)
///
public static NDarray Predict(NDarray? inputs)
{
//NDarry转为张量,输入是Nx80像素x80像素x3RGB
var inputTensor = inputs?.ToDenseTensor();
//需要明确指出模型的输入参数名字,如果不知道,请使用工具Netron
var input = new List<NamedOnnxValue> { NamedOnnxValue.CreateFromTensor<float>("input_11", inputTensor) };
var session = new InferenceSession(Path.Combine(System.AppDomain.CurrentDomain.BaseDirectory, "Assets/model.onnx"));
var outputs = session?.Run(input).ToList().Last().AsEnumerable<float>().ToArray();
var outputarray = np.array<float>(outputs!);
//输出是Nx3
var arr = outputarray.reshape(inputs!.shape.Dimensions[0], 3);
//取列最大值,也就是分类得分最高的结果,输出为NX1
arr = np.argmax(arr, axis: 1);
return arr;
}
}
单元测试函数
[Fact]
public void TestMLFromOnnx()
{
using (var mat = LoadImages.Load("classific.png"))
{
var array = mat.ToNDarray();
//我的模型是需要多个数据合并为一个input_11的
array = np.concatenate((array, array));
var arr= ClassificWithOnnx.Predict(array);
//模型输出是0,1,2的分类结果
Assert.True(arr?.item<int>(0) == 0);
}
}