当前位置: 首页 > news >正文

C# + .Net6 实现TensorFlow图片分类

微软官网上发现一篇很有意思的文档:
教程:用于对图像进行分类的 ML.NET 分类模型 - ML.NET | Microsoft Learn

这篇教程写的很学院派,但有点碎,属于上课不能打一秒钟瞌睡的那种。好在还是给出了完整的代码:samples/Program.cs at main · dotnet/samples · GitHub

当然自己尝试前必要的先决条件还是要满足的。

1、用于训练的图片和两个tsv,以及最重要的模型文件要准备好。示例:samples/image-classifier-assets.zip at main · dotnet/samples · GitHub

2、模型文件也可以从这里下载:https://storage.googleapis.com/download.tensorflow.org/models/inception5h.zip

3、VS2022中,项目 -> 管理NuGet程序包 -> 浏览,添加如下四个包:

Microsoft.ML
Microsoft.ML.ImageAnalytics
Microsoft.ML.TensorFlow
SciSharp.TensorFlow.Redist

 严格按照教程顺利跑通。本着能偷懒就偷懒的原则,开始对代码进行简化:
1、训练图集和tsv就暂先都直接硬编码了。实践证明如果所有文件在同一个目录下是没问题的:

static readonly string _imagesFolder = @"D:\temp\ForTraining";
static readonly string _trainTagsTsv = @"D:\temp\ForTraining\tags.tsv";
static readonly string _testTagsTsv = @"D:\temp\ForTraining\test-tags.tsv";
static readonly string _inceptionTensorFlowModel = @"D:\temp\ForTraining\tensorflow_inception_graph.pb";

否则按照文档的说法还要修改这些文件的复制属性。直接给出绝对路径可规避这个问题。

  1. 在“解决方案资源管理器”中,右键单击资产目录和子目录中的每个文件,再选择“属性”。 

  2. 在“高级”下,将“复制到输出目录”的值更改为“如果较新则复制” 。

2、 Demo里并未给出保存训练好的模型的代码。这意味着每次执行都要重新训练一次,效率比较低。所以稍微优化了一下代码:

public static ITransformer GenerateModel(MLContext mlContext)
{// 略// ......// 保存训练好的模型mlContext.Model.Save(model, trainingData.Schema, "model.zip");return model;
}

3、图片识别的代码另起了一个项目(原项目中屏蔽掉ClassifySingleImage相关代码),同样要导入那堆NuGet:

        static void Main(string[] args){if (args.Length == 0){Console.WriteLine("请输入预测的图片路径。");return;}string fn = args[0].Trim();if (!File.Exists(fn)){Console.WriteLine("文件不存在。");return;}// Create MLContext to be shared across the model creation workflow objectsMLContext mlContext = new();// 识别模式// 训练好的模型文件可复制到指定位置DataViewSchema modelSchema;// Load trained modelITransformer model = mlContext.Model.Load(@"D:\temp\ForTraining\model.zip", out modelSchema);// <SnippetCallClassifySingleImage>ClassifySingleImage(mlContext, model, fn);// </SnippetCallClassifySingleImage>}public static void ClassifySingleImage(MLContext mlContext, ITransformer model,string _predictSingleImage){// 无需修改,略// ......}/// 略

所以,接下来开发一个工具,用来生成tags.tsv和test-tags.tsv。嗯,思路已经有了。

相关文章:

C# + .Net6 实现TensorFlow图片分类

微软官网上发现一篇很有意思的文档&#xff1a;教程&#xff1a;用于对图像进行分类的 ML.NET 分类模型 - ML.NET | Microsoft Learn 这篇教程写的很学院派&#xff0c;但有点碎&#xff0c;属于上课不能打一秒钟瞌睡的那种。好在还是给出了完整的代码&#xff1a;samples/Pro…...

Ngnix负载均衡和高可用集群及搭建与相关理论

Ngnix负载均衡和高可用集群及搭建与相关理论 全文目录 Ngnix负载均衡和高可用集群及搭建与相关理论高可能保持原理配置 keepalived&#xff1a;配置keepalived的IP将外部域名解析到Keepalived的虚拟IP上如何验证配置的正确性Nginx专用调试工具ngx_conf_t如何对前后端多台服务器…...

2022年宜昌市网络搭建与应用竞赛样题(三)

网络搭建与应用竞赛样题&#xff08;三&#xff09; 技能要求 &#xff08;总分1000分&#xff09; 竞赛说明 一、竞赛内容分布 “网络搭建与应用”竞赛共分三个部分&#xff0c;其中&#xff1a; 第一部分&#xff1a;网络搭建及安全部署项目&#xff08;500分&#xff0…...

为什么PCB设计完成后需要放置mark点

PCB设计中的Mark点是指一些标记点&#xff0c;通常用于促进PCB制造和组装过程中的准确性和一致性。这些标记点在制造过程中可以帮助操作员进行自动化定位&#xff0c;从而确保所有部件都被正确组装到其正确位置&#xff0c;这对于确保产品的质量和可靠性至关重要。 下面&#…...

代理IP:IP代理技术与Socks5协议

代理IP是一种用于隐藏真实IP地址的技术&#xff0c;它可以将请求发送至代理服务器&#xff0c;再由代理服务器转发请求至目标网站。代理服务器会在请求过程中替换真实IP地址&#xff0c;从而保护用户的隐私和安全。在网络爬虫、反爬虫、匿名访问等场景中&#xff0c;代理IP技术…...

如何让java程序员生涯更顺利?我聊聊提升技术水平的五个方面

今天我想和大家聊聊程序员职业发展的问题。相信大家都知道&#xff0c;IT公司因为各种原因裁员&#xff0c;对程序员的前途发展都是不利的。特别是等到你30多岁&#xff0c;上有老下有小&#xff0c;仍然要加班&#xff0c;与年轻人竞争体力和智力&#xff0c;这是很艰难的。如…...

快速排序、希尔排序、归并排序、堆排序、插入排序、冒泡排序、选择排序(递归、非递归)C语言详解

1.排序的概念及其运用 1.1排序的概念 排序&#xff1a;所谓排序&#xff0c;就是使一串记录&#xff0c;按照其中的某个或某些关键字的大小&#xff0c;递增或递减的排列起来的操作。 稳定性&#xff1a;假定在待排序的记录序列中&#xff0c;存在多个具有相同的关键字的记录&a…...

ChatGPT一键私有部署,全网可用,让访问、问答不再受限,且安全稳定!

前言 ChatGPT由于在访问上有一些限制&#xff0c;使用并不便利。目前国内可以直接访问的大部分是调用API返回结果&#xff0c;我们去使用时总会有次数限制&#xff0c;而且它们可能随便崩掉。 其实&#xff0c;目前我们访问过的大部分国内的网页包括UI&#xff0c;其实是套用了…...

自学黑客(网络安全),一般人我劝你还是算了吧

一、自学网络安全学习的误区和陷阱 1.不要试图先成为一名程序员&#xff08;以编程为基础的学习&#xff09;再开始学习 我在之前的回答中&#xff0c;我都一再强调不要以编程为基础再开始学习网络安全&#xff0c;一般来说&#xff0c;学习编程不但学习周期长&#xff0c;而…...

盘“底座”,盘出新生意经

本文转自首席信息官 作者 徐蕊 导读 卖“底座”&#xff0c;这是一门新的生意&#xff0c;也是用友与友商差异化的商业竞争优势所在。 大型企业都在建“数智化底座” 有这样两类企业&#xff0c;他们截然不同&#xff0c;但在数智化的建设上殊途同归。 随着中国经济的发展&a…...

《花雕学AI》Poe:一个让你和 AI 成为朋友的平台,带你探索 ChatGPT4 和其他 八种AI 模型的奥秘

你是否曾经梦想过&#xff0c;能够在一个平台上&#xff0c;和多种不同的 AI 模型进行有趣、有用、有深度的对话&#xff0c;甚至还能轻松地把你的对话分享给其他人&#xff1f;如果你有这样的梦想&#xff0c;那么 Poe 一站式 AI 工具箱就是你的不二之选&#xff01; Poe 是国…...

单片机GD32F303RCT6 (Macos环境)开发 (十五)—— i2c1采用DMA方式的读写函数

i2c1采用DMA方式的读写函数 1、关于i2c1的DMA的映射如图 2、关于代码的宏定义配置 Application目录的Makefile中 ENABLE_I2C_TEST yes才会编译I2C1的相关代码。 同时修改i2c.h文件&#xff0c;定义I2C1_MODE为I2C1_MODE_DMA&#xff0c;这样i2c1的配置为dma模式。 #define …...

通知短信 API 技术细节以及发送流程机制原理解析

引言 短信是一种简单、直接、高效的通信方式&#xff0c;被广泛应用于各个领域。在移动互联网时代&#xff0c;短信成为了客户服务、政府通知、公共服务等方面的重要工具。为了更好地利用短信这种通信方式&#xff0c;通知短信 API应运而生。短信API可以帮助企业、政府和应用程…...

Protobuf: 高效数据传输的秘密武器

当涉及到网络通信和数据存储时&#xff0c;数据序列化一直都是一个重要的话题&#xff1b;特别是现在很多公司都在推行微服务&#xff0c;数据序列化更是重中之重&#xff0c;通常会选择使用 JSON 作为数据交换格式&#xff0c;且 JSON 已经成为业界的主流。但是 Google 这么大…...

第五十四章 Unity 移动平台输入(下)

本章节我们介绍一个模拟器插件。这种插件比较多&#xff0c;比如EasyTouch&#xff0c;Lean Touch&#xff0c;Joystick Pack等等。EasyTouch是一个使用非常广泛的插件&#xff0c;支持点击&#xff0c;拖拽&#xff0c;遥感等很多常用功能。不过遗憾的是&#xff0c;该插件已经…...

KD305Y带吸收比极化指数兆欧表

一、概述 KD305Y绝缘电阻测试仪对众多的电力设备如&#xff1a;电缆、电机、发电机、变压器、互感器、高压开关、避雷器等要求做一系列的绝缘性能试验&#xff0c;首先是要做绝缘电阻测试。近年来随着电力事业的飞速发展,大容量设备的使用不断增加&#xff0c;用普通的兆欧表无…...

磁盘空间不足怎么办?释放磁盘空间的4种方法

虽然现在硬盘的空间越来越大&#xff0c;但是在这个数据爆炸的时代中&#xff0c;总是会觉得存储空间不够用&#xff0c;一不注意磁盘就满了&#xff0c;那么除了清空回收站、卸载某些程序外&#xff0c;还能怎么释放磁盘空间呢&#xff1f; 方案一&#xff1a;禁用休眠 休眠是…...

ChatGPT调教指北,技巧就是效率!

技巧就是效率 很多人都知道ChatGPT很火很强&#xff0c;几乎无所不能&#xff0c;但跨越了重重门槛之才有机会使用的时候却有些迷茫&#xff0c;一时间不知道如何使用它。如果你就是把他当作一个普通的智能助手来看待&#xff0c;那与小爱同学有什么区别&#xff1f;甚至还差劲…...

Android启动流程(五)——init进程对子进程的监控

init进程会读取rc文件&#xff0c;然后孵化很多其他系统服务进程&#xff0c;为防止子进程死亡后称为僵尸进程&#xff0c;init需要监测子进程是否死亡&#xff0c;如果死亡&#xff0c;则清除子进程资源&#xff0c;并重新拉起进程。 system/core/init/init.cpp InstallSigna…...

Python每日一练:蚂蚁家族(详解集合法)

文章目录 前言一、题目二、代码分析总结 前言 这题挺有意思&#xff0c;感觉评简单难度有点低了&#xff0c;如果正经用无向图来做&#xff0c;代码还是有点长的。首先得建立节点&#xff0c;估计除第一个和最后一个每个节点都是一条线连进&#xff0c;一条线连出的。就可以这…...

如何将联系人从 iPhone 转移到 Android

从 iPhone 换到 Android 手机时&#xff0c;你可能需要保留重要的数据&#xff0c;例如通讯录。好在&#xff0c;将通讯录从 iPhone 转移到 Android 手机非常简单&#xff0c;你可以从本文中学习 6 种可靠的方法&#xff0c;确保随时保持连接&#xff0c;不错过任何信息。 第 1…...

docker 部署发现spring.profiles.active 问题

报错&#xff1a; org.springframework.boot.context.config.InvalidConfigDataPropertyException: Property spring.profiles.active imported from location class path resource [application-test.yml] is invalid in a profile specific resource [origin: class path re…...

Java求职者面试指南:计算机基础与源码原理深度解析

Java求职者面试指南&#xff1a;计算机基础与源码原理深度解析 第一轮提问&#xff1a;基础概念问题 1. 请解释什么是进程和线程的区别&#xff1f; 面试官&#xff1a;进程是程序的一次执行过程&#xff0c;是系统进行资源分配和调度的基本单位&#xff1b;而线程是进程中的…...

uniapp 小程序 学习(一)

利用Hbuilder 创建项目 运行到内置浏览器看效果 下载微信小程序 安装到Hbuilder 下载地址 &#xff1a;开发者工具默认安装 设置服务端口号 在Hbuilder中设置微信小程序 配置 找到运行设置&#xff0c;将微信开发者工具放入到Hbuilder中&#xff0c; 打开后出现 如下 bug 解…...

Pydantic + Function Calling的结合

1、Pydantic Pydantic 是一个 Python 库&#xff0c;用于数据验证和设置管理&#xff0c;通过 Python 类型注解强制执行数据类型。它广泛用于 API 开发&#xff08;如 FastAPI&#xff09;、配置管理和数据解析&#xff0c;核心功能包括&#xff1a; 数据验证&#xff1a;通过…...

[特殊字符] 手撸 Redis 互斥锁那些坑

&#x1f4d6; 手撸 Redis 互斥锁那些坑 最近搞业务遇到高并发下同一个 key 的互斥操作&#xff0c;想实现分布式环境下的互斥锁。于是私下顺手手撸了个基于 Redis 的简单互斥锁&#xff0c;也顺便跟 Redisson 的 RLock 机制对比了下&#xff0c;记录一波&#xff0c;别踩我踩过…...

JS红宝书笔记 - 3.3 变量

要定义变量&#xff0c;可以使用var操作符&#xff0c;后跟变量名 ES实现变量初始化&#xff0c;因此可以同时定义变量并设置它的值 使用var操作符定义的变量会成为包含它的函数的局部变量。 在函数内定义变量时省略var操作符&#xff0c;可以创建一个全局变量 如果需要定义…...

基于stm32F10x 系列微控制器的智能电子琴(附完整项目源码、详细接线及讲解视频)

注&#xff1a;文章末尾网盘链接中自取成品使用演示视频、项目源码、项目文档 所用硬件&#xff1a;STM32F103C8T6、无源蜂鸣器、44矩阵键盘、flash存储模块、OLED显示屏、RGB三色灯、面包板、杜邦线、usb转ttl串口 stm32f103c8t6 面包板 …...

Qwen系列之Qwen3解读:最强开源模型的细节拆解

文章目录 1.1分钟快览2.模型架构2.1.Dense模型2.2.MoE模型 3.预训练阶段3.1.数据3.2.训练3.3.评估 4.后训练阶段S1: 长链思维冷启动S2: 推理强化学习S3: 思考模式融合S4: 通用强化学习 5.全家桶中的小模型训练评估评估数据集评估细节评估效果弱智评估和民间Arena 分析展望 如果…...

__VUE_PROD_HYDRATION_MISMATCH_DETAILS__ is not explicitly defined.

这个警告表明您在使用Vue的esm-bundler构建版本时&#xff0c;未明确定义编译时特性标志。以下是详细解释和解决方案&#xff1a; ‌问题原因‌&#xff1a; 该标志是Vue 3.4引入的编译时特性标志&#xff0c;用于控制生产环境下SSR水合不匹配错误的详细报告1使用esm-bundler…...