13.3 Windows中模型的部署

您所在的位置:网站首页 bitmap中有 13.3 Windows中模型的部署

13.3 Windows中模型的部署

2023-03-26 03:52| 来源: 网络整理| 查看: 265

13.3 Windows中模型的部署 13.3 Windows中模型的部署⚓︎

微软开源了ONNX运行时库(ONNX Runtime),可以进行高性能的推理,支持主流三大操作系统平台,支持使用GPU,同时提供Python、C#、C/C++、Ruby等开发语言,能满足各种场景的使用。

下面我们将使用前面生成的mnist.onnx,创建一个Windows桌面应用,实现手写数字的识别。这里使用C#开发语言,需要安装Visual Studio开发环境。

创建WPF项目

打开Visual Studio 2017,新建项目,在Visual C#分类中选择WPF应用,填写项目名称为OnnxDemo,点击确定,即可完成一个空白项目的创建,如图13-10所示。

图13-10 创建WPF项目

添加模型文件到项目中

打开解决方案资源管理器中,在项目上点右键->添加->现有项,如图13-11所示。

图13-11 添加现有项

在弹出的对话框中,将文件类型过滤器改为所有文件,然后导航到模型所在目录,选择模型文件并添加,如图13-12所示。本示例中使用的模型文件是mnist.onnx。

图13-12 选择模型文件

模型是在应用运行期间加载的,所以在编译时需要将模型复制到运行目录下。在模型文件上点右键,属性,然后在属性面板上,将生成操作属性改为内容,将复制到输出目录属性改为如果较新则复制。如图13-13所示。

图13-13 修改文件属性

添加OnnxRuntime库

微软开源的ONNX运行时库(ONNX Runtime)库提供了NuGet包,可以很方便的集成到Visual Studio项目中。

打开解决方案资源管理器,在引用上点右键,管理NuGet程序包。如图13-14所示。

图13-14 管理NuGet程序包

在打开的NuGet包管理器中,切换到浏览选项卡,搜索onnxruntime,找到Microsoft.ML.OnnxRuntime包,当前版本是1.0.0,点击安装,按提示完成安装即可。该版本不支持AnyCPU平台,所以需要将项目的目标架构显式的改为x64或x86。在解决方案上点右键,选择配置管理器。如图13-15所示。

图13-15 打开配置管理器

在配置管理器对话框中,将活动解决方案平台切换为x64或x86。如果没有x64和x86,在下拉框中选择新建,按提示新建x64或x86平台。如图13-16所示。

图13-16 新建解决方案平台

设计界面

打开MainWindow.xaml,将整个Grid片段替换为如下代码:

显示效果如图13-17所示。

图13-17 应用程序界面设计

其中:

inkCanvas是写数字的画布,由于训练mnist用的数据集是黑色背景白色字,所以这里将画布也设置为黑色背景 lbResult文本控件用来显示识别的结果 btnClean按钮用来清除之前的画布

然后在MainWindow构造函数中调用InitInk方法初始化画布,设置画笔颜色为白色:

private void InitInk() { // 将画笔改为白色 var attr = new DrawingAttributes(); attr.Color = Colors.White; attr.IgnorePressure = true; attr.StylusTip = StylusTip.Ellipse; attr.Height = 24; attr.Width = 24; inkCanvas.DefaultDrawingAttributes = attr; // 每次画完一笔时,都触发此事件进行识别 inkCanvas.StrokeCollected += InkCanvas_StrokeCollected; } private void InkCanvas_StrokeCollected(object sender, InkCanvasStrokeCollectedEventArgs e) { // 从画布中进行识别 RecogNumberFromInk(); }

其中,RecogNumberFromInk就是对画布中的内容进行识别,在后面的小节中再添加实现。

然后添加btnClean按钮事件的实现:

private void BtnClean_Click(object sender, RoutedEventArgs e) { // 清除画布 inkCanvas.Strokes.Clear(); lbResult.Text = string.Empty; }

画布数据预处理

前面图13-9中可以看到,输入fc1x是一个大小为1x784的float数组,对应的是28x28大小图片的每个像素点的色值,输出activation3y是1x10的float数组,分别代表识别为数字0-9的得分,值最大的即为识别结果。

因此这里需要添加几个函数对画布数据进行处理,转为模型可以接受的数据。以下几个函数分别是将画布渲染到28x28的图片,读取每个像素点的值,生成模型需要数组:

private BitmapSource RenderToBitmap(FrameworkElement canvas, int scaledWidth, int scaledHeight) { // 将画布渲染到bitmap上 RenderTargetBitmap rtb = new RenderTargetBitmap((int)canvas.Width, (int)canvas.Height, 96d, 96d, PixelFormats.Default); rtb.Render(canvas); // 调整bitmap的大小为28*28,与模型的输入保持一致 TransformedBitmap tfb = new TransformedBitmap(rtb, new ScaleTransform(scaledWidth / rtb.Width, scaledHeight / rtb.Height)); return tfb; } public byte[] GetPixels(BitmapSource source) { if (source.Format != PixelFormats.Bgra32) source = new FormatConvertedBitmap(source, PixelFormats.Bgra32, null, 0); int width = source.PixelWidth; int height = source.PixelHeight; byte[] data = new byte[width * 4 * height]; source.CopyPixels(data, width * 4, 0); return data; } public float[] GetInputDataFromInk() { var bitmap = RenderToBitmap(inkCanvas, 28, 28); var imageBytes = GetPixels(bitmap); float[] data = new float[784]; for (int i = 0; i


【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3