AI看图识熊实战(一)

news2024/12/26 11:41:28

使用ONNX Runtime封装onnx模型并推理

进行这一步之前,请确保已正确安装配置了Visual Studio 2017 和 C#开发环境。

项目的代码也可以在这里找到,下面的步骤是带着大家从头到尾做一遍。

界面设计

创建Windows窗体应用(.NET Framework)项目,这里给项目起名ClassifyBear。

在解决方案资源管理器中找到Form1.cs,双击,打开界面设计器。从工具箱中向Form中依次拖入控件并调整,最终效果如下图所示:

左侧从上下到依次是:

  • Label控件,将内容改为“输入要识别的图片地址:”

  • TextBox控件,可以将控件拉长一些,方便输入URL

  • Button控件,将内容改为“识别”

  • Lable控件,将label的内容清空,用来显示识别后的结果。因为label也没有边框,所以在界面看不出来。可以将此控件的字体调大一些,能更清楚的显示推理结果。

右侧的控件是一个PictureBox,用来预览输入的图片,同时,我们也从这个控件中取出对应的图片数据,传给我们的模型推理类库去推理。建议将控件属性的SizeMode更改为StretchImage,并将控件长和宽设置为同样的值,保持一个正方形的形状,这样可以方便我们直观的了解模型的输入,因为在前面查看模型信息的时候也看到了,该模型的输入图片应是正方形(当前最新的定制化视觉服务导出的模型需要的输入图片大小为224*224)。

添加模型文件到项目中

打开解决方案资源管理器中,在项目上点右键->添加->现有项,在弹出的对话框中,将文件类型过滤器改为所有文件,然后导航到模型所在目录,选择模型文件并添加。本示例中使用的模型文件是BearModel.onnx

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

添加OnnxRuntime库

微软开源的OnnxRuntime库提供了NuGet包,可以很方便的集成到Visual Studio项目中。

打开解决方案资源管理器,在引用上点右键,管理NuGet程序包。

在打开的NuGet包管理器中,切换到浏览选项卡,搜索onnxruntime,找到Microsoft.ML.OnnxRuntime包,当前版本是0.4.0,点击安装,稍等片刻,按提示即可完成安装。

当前NuGet发布的OnnxRuntime库支持x64及x86架构的运行库,建议使用x64的,所以这里将项目的目标架构改为x64。

在解决方案上点右键,选择配置管理器。在配置管理器对话框中,将活动解决方案平台切换为x64。如果没有x64,在下拉框中选择新建,按提示新建x64平台。

处理输入并加载模型进行推理

在Form1.cs上点右键,选择查看代码,打开Form1.cs的代码编辑窗口。

添加一个成员变量

// 使用Netron查看模型,得到模型的输入应为224*224大小的图片
private const int imageSize = 224;

回到Form1的设计界面,双击识别按钮,会自动跳转到代码页面并添加了button1_Click方法,在其中添加以下代码:

首先,每次点击识别按钮时都先将界面上显示的上一次的结果清除

// 识别之前先重置界面显示的内容
label1.Text = string.Empty;
pictureBox1.Image = null;
pictureBox1.Refresh();


然后,让图片控件加载图片

bool isSuccess = false;
try
{
    pictureBox1.Load(textBox1.Text);
    isSuccess = true;
}
catch (Exception ex)
{
    MessageBox.Show($"读取图片时出现错误:{ex.Message}");
    throw;
}


如果加载成功,将图片数据处理成需要的大小,然后加载模型进行推理。

if (isSuccess)
{
    // 图片加载成功后,从图片控件中取出224*224的位图对象
    Bitmap bitmap = new Bitmap(pictureBox1.Image, imageSize, imageSize);
​
    float[] imageArray = new float[imageSize * imageSize * 3];
​
    // 按照先行后列的方式依次取出图片的每个像素值
    for (int y = 0; y < imageSize; y++)
    {
        for (int x = 0; x < imageSize; x++)
        {
            var color = bitmap.GetPixel(x, y);
​
            // 使用Netron查看模型的输入发现
            // 需要依次放置224 *224的蓝色分量、224*224的绿色分量、224*224的红色分量
            imageArray[y * imageSize + x] = color.B;
            imageArray[y * imageSize + x + 1 * imageSize * imageSize] = color.G;
            imageArray[y * imageSize + x + 2 * imageSize * imageSize] = color.R;
        }
    }
​
    // 设置要加载的模型的路径,跟据需要改为你的模型名称
    string modelPath = AppDomain.CurrentDomain.BaseDirectory + "BearModel.onnx";
​
    using (var session = new InferenceSession(modelPath))
    {
        var container = new List<NamedOnnxValue>();
​
        // 用Netron看到需要的输入类型是float32[None,3,224,224]
        // 第一维None表示可以传入多张图片进行推理
        // 这里只使用一张图片,所以使用的输入数据尺寸为[1, 3, 224, 224]
        var shape = new int[] { 1, 3, imageSize, imageSize };
        var tensor = new DenseTensor<float>(imageArray, shape);
​
        // 支持多个输入,对于mnist模型,只需要一个输入,输入的名称是data
        container.Add(NamedOnnxValue.CreateFromTensor<float>("data", tensor));
​
        // 推理
        var results = session.Run(container);
​
        // 输出结果有两个,classLabel和loss,这里只关心classLabel
        var label = results.FirstOrDefault(item => item.Name == "classLabel")? // 取出名为classLabel的输出
            .AsTensor<string>()?
            .FirstOrDefault(); // 支持多张图片同时推理,这里只推理了一张,取第一个结果值
​
        // 显示在控件中
        label1.Text = label;
    }
}

注意,这里的数据转换一定要按照前面查看的模型的信息来转换,图片大小需要长宽都是224像素,并且要依次放置所有的蓝色分量、所有的绿色分量、所有的红色分量,如果顺序不正确,不能达到最佳的推理结果。

测试

编译运行,然后在网上找一张熊的图片,把地址填到输入框内,然后点击识别按钮,就可以看到识别的结果了。注意,这个URL应该是图片的URL,而不是包含该图片的网页的URL。

如果运行时遇到类似于找不到onnxruntime的dll的问题,可能是编译时相关库没有拷到运行目录下,可以尝试先清理解决方案,然后再重新编译解决方案。也可以手动到解决方案目录\packages\Microsoft.ML.OnnxRuntime.0.4.0\runtimes\win-x64\native下将onnxruntime.dll拷到程序运行目录

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1362598.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

CRC32的原理介绍以及查表法实现和多项式相除实现

1、CRC32的生成多项式 多项式系数提取出来&#xff0c;改写位16进制数为&#xff1a;0x104C11DB7&#xff0c;如果转换为33个二进制数[1, 0, 0, 0, 0, 0, 1, 0, 0, 1, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 1, 1, 0, 1, 1, 0, 1, 1, 0, 1, 1, 1] &#xff0c;那么从左到右对…

工地云平台源码,智慧工地源码,Spring Cloud智慧工地管理系统源码

智慧工地是一种基于信息技术和大数据应用的智能化管理平台&#xff0c;旨在提升建筑施工现场的安全、效率和质量。通过物联网、云计算、人工智能等技术手段&#xff0c;智慧工地可以对施工现场的各个要素进行全面感知、实时交互和智能分析&#xff0c;以实现更高效、更安全、更…

【LMM 015】LAMM:多模态指令微调数据集,框架和基准

论文标题&#xff1a;LAMM: Language-Assisted Multi-Modal Instruction-Tuning Dataset, Framework, and Benchmark 论文作者&#xff1a;Zhenfei Yin, Jiong Wang, Jianjian Cao, Zhelun Shi, Dingning Liu, Mukai Li, Lu Sheng, Lei Bai, Xiaoshui Huang, Zhiyong Wang, Jin…

视觉检测不合格品剔除FC(Smart PLC简单状态机编程应用)

视觉系统检测到不合格产品后&#xff0c;往往都需要控制我们的剔除电磁阀吹气剔除不合格产品&#xff0c;三菱PLC里的推荐编程方法&#xff0c;可以参考下面的链接文章&#xff1a; https://rxxw-control.blog.csdn.net/article/details/125027866https://rxxw-control.blog.c…

【算法每日一练]-图论(保姆级教程篇14 )#会议(模板题) #医院设置 #虫洞 #无序字母对 #旅行计划 #最优贸易

目录 今日知识点&#xff1a; 求数的重心先dfs出d[1]和cnt[i]&#xff0c;然后从1进行dp求解所有d[i] 两两点配对的建图方式&#xff0c;检查是否有环 无向图欧拉路径路径输出 topodp求以i为终点的游览城市数 建立分层图转化盈利问题成求最长路 会议&#xff08;模板题&a…

I.MX6ULL开发笔记(二)——硬件外设操作

0x01 点亮第一个RGB灯 在文章http://t.csdnimg.cn/EGWt9中有介绍Linux下文件目录&#xff0c;那么在Linux系统下&#xff0c;RGB灯也是一个设备&#xff0c;所以我们需要到/sys目录下去操作这个设备。 之后&#xff0c;我们进入到class目录&#xff0c;这里挂载着开发板上的外…

【数据仓库与联机分析处理】多维数据模型

目录 一、数据立方体 二、数据模型 &#xff08;一&#xff09;星形模型 &#xff08;二&#xff09;雪花模式 &#xff08;三&#xff09;事实星座模式 三、多维数据模型中的OLAP操作 &#xff08;一&#xff09;下钻 &#xff08;二&#xff09;上卷 &#xff08;三…

【GitHub】-design-pattern-extend(设计模式扩展)

写在前面 偶然间看到一篇文章 《Java 中保持扩展性的几种套路和实现》&#xff0c;写的不错&#xff0c;但是类图画的差了点儿意思。于是&#xff0c;自己动手画了画&#xff0c;对其中的内容作了一些调整&#xff0c;对包做了进一步划分&#xff0c;便于理解消化。以下是对Git…

第11章 GUI Page462~476 步骤二十三,二十四,二十五 Undo/Redo ③实现“Undo/Redo”菜单项

工程六 添加“编辑”菜单和子菜单 菜单ID分别为 idMenuEditUndo 和 idMenuEditRedo 热键&#xff08;快捷键&#xff09;分别为CtrlZ 和 CtrlShiftZ 变量名分别为 MenuItemEditUndo 和 MenuItemEditRedo 分别添加事件 ActionLink类增加成员函数 运行效果&#xff1a;“添加…

【C语言】Linux实现高并发处理的过程

一、实现高并发的几种策略 C语言本身并没有内建的多线程支持&#xff08;新版C语言支持&#xff0c;但用得不多&#xff09;&#xff0c;但是在多数操作系统中&#xff0c;可以使用库来实现多线程编程。例如&#xff0c;在POSIX兼容系统上&#xff0c;可以使用 pthreads 库来创…

【Web开发】会话管理与无 Cookie 环境下的实现策略

&#x1f34e;个人博客&#xff1a;个人主页 &#x1f3c6;个人专栏&#xff1a; Web开发 ⛳️ 功不唐捐&#xff0c;玉汝于成 目录 前言 正文 问题&#xff1a; 思路&#xff1a; 方法&#xff1a; 结语 我的其他博客 前言 在当今Web应用程序中&#xff0c;会话…

实时语义分割模型PP-LiteSeg论文解读

paper&#xff1a;PP-LiteSeg: A Superior Real-Time Semantic Segmentation Model official implementation&#xff1a;https://github.com/PaddlePaddle/PaddleSeg/blob/release/2.8/paddleseg/models/pp_liteseg.py 本文的创新点 提出了一种灵活的轻量级解码器&#xf…

力扣:438. 找到字符串中所有字母异位词 题解

Problem: 438. 找到字符串中所有字母异位词 438. 找到字符串中所有字母异位词 预备知识解题思路复杂度Code其它细节推荐博客或题目博客题目滑动窗口哈希表 预备知识 此题用到了双指针算法中的滑动窗口思想&#xff0c;以及哈希表的运用。c中是unordered_map。如果对此不了解的u…

基于Spring-boot-websocket的聊天应用开发总结

目录 1.概述 1.1 Websocket 1.2 STOMP 1.3 源码 2.Springboot集成WS 2.1 添加依赖 2.2 ws配置 2.2.1 WebSocketMessageBrokerConfigurer 2.2.2 ChatController 2.2.3 ChatInRoomController 2.2.4 ChatToUserController 2.3 前端聊天配置 2.3.1 index.html和main.j…

路由器01_工作原理

一、回顾交换机工作原理 交换机里面维护了一张MAC地址表&#xff0c;主要记录的是MAC地址和接口的对应关系。 交换机在初始状态下&#xff0c;MAC地址表是空的&#xff0c;当收到一个来自某接口的数据时&#xff0c;首先查看数据帧中的MAC地址表&#xff0c;对照自己的MAC地址…

MySQL进阶篇(二) 索引

一、索引概述 1. 介绍 索引&#xff08;index&#xff09;是帮助 MySQL 高效获取数据 的 数据结构&#xff08;有序&#xff09;。在数据之外&#xff0c;数据库系统还维护着满足特定查找算法的数据结构&#xff0c;这些数据结构以某种方式引用&#xff08;指向&#xff09;数…

React 实现拖放功能

介绍 本篇文章将会使用react实现简单拖放功能。 样例 布局拖放 LayoutResize.js import React, {useState} from "react"; import { Button } from "antd"; import "./LayoutResize.css";export const LayoutResize () > {const [state,…

imgaug库指南(六):从入门到精通的【图像增强】之旅

引言 在深度学习和计算机视觉的世界里&#xff0c;数据是模型训练的基石&#xff0c;其质量与数量直接影响着模型的性能。然而&#xff0c;获取大量高质量的标注数据往往需要耗费大量的时间和资源。正因如此&#xff0c;数据增强技术应运而生&#xff0c;成为了解决这一问题的…

海康威视安全接入网关 任意文件读取漏洞复现

0x01 产品简介 海康威视安全接入网关是一种网络安全产品,旨在提供安全、可靠的远程访问和连接解决方案. 0x02 漏洞概述 海康威视安全接入网关使用Jquery-1.7.2 , 该版本存在任意文件读取漏洞,可获取服务器内部敏感信息泄露(安博通应用网关也存在此漏洞) 0x03 复现环境 …

未完成销量任务的智己汽车突发大规模车机故障,竞争压力不小

2024年刚开年&#xff0c;智己汽车便上演了一出“开门黑”。 近日&#xff0c;不少车主在社交平台发帖&#xff0c;反映智己LS6出现大规模车机故障&#xff0c;包括但不限于主驾驶屏幕不显示车速、档位、行驶里程&#xff0c;左右转盲区显示失效&#xff0c;无转向灯、雷达提醒…