AI與.NET技術實操系列(六):實現圖像分類模型的部署與調用

引言

人工智能(AI)技術的迅猛發展推動了各行各業的數字化轉型。圖像分類,作為計算機視覺領域的核心技術之一,能夠讓機器自動識別圖像中的物體、場景或特征,已廣泛應用于醫療診斷、安防監控、自動駕駛和電子商務等領域。

與此同時,.NET 平臺憑借其高效性、跨平臺能力和強大的 C# 編程語言支持,成為開發者構建企業級應用的首選技術棧。將 AI 圖像分類模型與 .NET 技術結合,不僅能充分發揮兩者的優勢,還能為開發者提供一種高效、直觀的實現方式。

本文將詳細介紹如何在 .NET 環境下使用 C# 部署和調用 AI 圖像分類模型。我們將從環境搭建、模型選擇,到模型調用,再到實際應用場景,逐步展開講解,并提供豐富的代碼示例和實踐指導,幫助開發者快速上手并應用到實際項目中。


準備工作

在開始實現圖像分類之前,我們需要準備必要的開發環境和工具。以下是所需的軟件和庫:

  • Visual Studio:Visual Studio 2022。
  • .NET SDK:安裝 .NET 6.0 或更高版本,確保支持最新的功能和性能優化。
  • ML.NET:微軟提供的開源機器學習框架,專為 .NET 開發者設計,支持模型訓練和推理。
  • 模型文件:我們將使用預訓練的圖像分類模型 tensorflow_inception_graph.pb。

安裝步驟

創建項目并添加依賴:在命令行中運行以下命令,創建一個控制臺應用程序并安裝必要的 NuGet 包:

dotnet new console -n ImageClassificationDemo
cd ImageClassificationDemo
dotnet add package Microsoft.ML
dotnet add package Microsoft.ML.ImageAnalytics
dotnet add package Microsoft.ML.TensorFlow
dotnet add package SciSharp.TensorFlow.Redist

完成以上步驟后,你的環境就準備好了。接下來,我們將選擇一個合適的圖像分類模型。


圖像分類模型的選擇

圖像分類模型是基于監督學習的神經網絡,其目標是將輸入圖像分配到預定義的類別中。在選擇模型時,我們需要考慮模型的性能、計算復雜度和適用場景。以下是幾種常見的圖像分類模型:

  • 卷積神經網絡(CNN):如 LeNet、AlexNet 和 VGGNet,適合基本的圖像分類任務,但層數較深時可能面臨梯度消失問題。
  • 殘差網絡(ResNet):通過引入殘差連接(skip connections),解決了深層網絡的訓練難題,適用于高精度分類任務。
  • EfficientNet:通過平衡網絡深度、寬度和分辨率,提供高效的性能,適合資源受限的場景。

模型訓練與導出

考慮到時間和資源成本,我們將直接使用預訓練的 tensorflow_inception_graph.pb 模型。如果你有自定義需求,可以使用以下步驟訓練并導出模型:

  1. 數據準備:收集并標注圖像數據集,分為訓練集和驗證集。
  2. 訓練模型:使用 TensorFlow 或 PyTorch 等框架訓練模型。
  3. 導出模型:利用框架提供的導出工具導出模型。

在本文中,我們選擇 tensorflow_inception_graph.pb 作為示例模型,這是一種由Google開發的高性能卷積神經網絡(CNN)架構。

該模塊通過并行使用不同大小的卷積核(如1x1、3x3、5x5)和池化層,提取圖像的多尺度特征。這種設計提高了模型在圖像分類任務中的表現,同時保持了計算效率。支持 1000 個類別的分類,且可以輕松集成到 .NET 中。

大家可以直接點擊 tensorflow_inception_graph.pb 下載(文章最后也有下載方式)預訓練的模型文件和分類文件,并將其放入項目目錄中。

也可以到github上下載(文章最后也有下載方式),里面的內容相對來說也更豐富些。


在 .NET 中調用模型

現在,我們進入核心部分:在 .NET 中調用 tensorflow_inception_graph.pb。以下是逐步實現的過程。

1. 創建 .NET 項目

使用命令行創建一個控制臺應用,項目基本結構如下:

ImageClassificationDemo/
├── ImageClassificationDemo.csproj
├── Program.cs
├── assets/inputs/inception/tensorflow_inception_graph.pb
├── assets/inputs/inception/imagenet_comp_graph_label_strings.txt

2. 定義輸入和輸出數據結構

如果在運行的時候報錯說找不到模型或者label文件,可以進行如下操作:

輸入類中定義數據的結構如下,后續會使用 TextLoader 加載數據時引用該類型。此處的類名為 ImageNetData

    public class ImageNetData{[LoadColumn(0)]public string ImagePath;[LoadColumn(1)]public string Label;public static IEnumerable<ImageNetData> ReadFromCsv(string file, string folder){return File.ReadAllLines(file).Select(x => x.Split('\t')).Select(x => new ImageNetData { ImagePath = Path.Combine(folder, x[0]), Label = x[1] } );}}public class ImageNetDataProbability : ImageNetData{public string PredictedLabel;public float Probability { get; set; }}

需要強調的是,ImageNetData 類中的標簽在使用 TensorFlow 模型進行評分時并沒有真正使用。而是在測試預測時使用它,這樣就可以將每個樣本數據的實際標簽與 TensorFlow 模型提供的預測標簽進行比較。

輸出類的結構如下:

public class ImageNetPrediction
{[ColumnName(TFModelScorer.InceptionSettings.outputTensorName)]public float[] PredictedLabels;
}

Inception 模型還需要幾個傳入的默認參數:

public struct ImageNetSettings
{public const int imageHeight = 224;public const int imageWidth = 224;public const float mean = 117;public const bool channelsLast = true;
}      

3. 定義 estimator 管道

在處理深度神經網絡時,必須使圖像適應網絡期望的格式。這就是圖像被調整大小然后轉換的原因(主要是像素值在所有R,G,B通道上被歸一化)。

var pipeline = mlContext.Transforms.LoadImages(outputColumnName: "input", imageFolder: imagesFolder, inputColumnName: nameof(ImageNetData.ImagePath)).Append(mlContext.Transforms.ResizeImages(outputColumnName: "input", imageWidth: ImageNetSettings.imageWidth, imageHeight: ImageNetSettings.imageHeight, inputColumnName: "input")).Append(mlContext.Transforms.ExtractPixels(outputColumnName: "input", interleavePixelColors: ImageNetSettings.channelsLast, offsetImage: ImageNetSettings.mean)).Append(mlContext.Model.LoadTensorFlowModel(modelLocation).ScoreTensorFlowModel(outputColumnNames: new[] { "softmax2" }, inputColumnNames: new[] { "input" },addBatchDimensionInput:true));

運行代碼后,模型將被成功加載到內存中,接下來我們可以調用它進行圖像分類。

通常情況下,這里經常報的錯就是輸入/輸出節點的名稱不正確,你可以通過 Netron (https://netron.app/)工具查看輸入/輸出節點的名稱。

因為這兩個節點的名稱后面會在 estimator 的定義中使用:在 inception 網絡的情況下,輸入張量命名為 ‘input’,輸出命名為 ‘softmax2’。

下圖是通過 Netron 讀取的 tensorflow_inception_graph.pb 模型分析圖:

輸入張量名

輸出張量名

4. 提取預測結果

填充 estimator 管道

ITransformer model = pipeline.Fit(data);
var predictionEngine = mlContext.Model.CreatePredictionEngine<ImageNetData, ImageNetPrediction>(model);

當獲得預測結果后,我們會在屬性中得到一個浮點數數組。數組中的每個位置都會分配到一個標簽。

例如,如果模型有5個不同的標簽,則數組將為length = 5。數組中的每個位置都表示標簽在該位置的概率;所有數組值(概率)的和等于1。

然后,您需要選擇最大的值(概率),并檢查配給了該位置的那個以填充 estimator 管道標簽。


調用模型進行圖像分類

接下來我們需要編寫代碼來加載圖像、進行預測并解析結果。

1. 準備素材與分類文件

定義圖像文件夾目錄和圖像分類目錄。以下代碼加載并預處理圖像:

string assetsRelativePath = @"../../../assets";
string assetsPath = GetAbsolutePath(assetsRelativePath);string tagsTsv = Path.Combine(assetsPath, "inputs", "images", "tags.tsv");
string imagesFolder = Path.Combine(assetsPath, "inputs", "images");
string inceptionPb = Path.Combine(assetsPath, "inputs", "inception", "tensorflow_inception_graph.pb");
string labelsTxt = Path.Combine(assetsPath, "inputs", "inception", "imagenet_comp_graph_label_strings.txt");

2. 加載模型

private PredictionEngine<ImageNetData, ImageNetPrediction> LoadModel(string dataLocation, string imagesFolder, string modelLocation)
{ConsoleWriteHeader("Read model");Console.WriteLine($"Model location: {modelLocation}");Console.WriteLine($"Images folder: {imagesFolder}");Console.WriteLine($"Training file: {dataLocation}");Console.WriteLine($"Default parameters: image size=({ImageNetSettings.imageWidth},{ImageNetSettings.imageHeight}), image mean: {ImageNetSettings.mean}");var data = mlContext.Data.LoadFromTextFile<ImageNetData>(dataLocation, hasHeader: true);var pipeline = mlContext.Transforms.LoadImages(outputColumnName: "input", imageFolder: imagesFolder, inputColumnName: nameof(ImageNetData.ImagePath)).Append(mlContext.Transforms.ResizeImages(outputColumnName: "input", imageWidth: ImageNetSettings.imageWidth, imageHeight: ImageNetSettings.imageHeight, inputColumnName: "input")).Append(mlContext.Transforms.ExtractPixels(outputColumnName: "input", interleavePixelColors: ImageNetSettings.channelsLast, offsetImage: ImageNetSettings.mean)).Append(mlContext.Model.LoadTensorFlowModel(modelLocation).ScoreTensorFlowModel(outputColumnNames: new[] { "softmax2" },inputColumnNames: new[] { "input" }, addBatchDimensionInput:true));ITransformer model = pipeline.Fit(data);var predictionEngine = mlContext.Model.CreatePredictionEngine<ImageNetData, ImageNetPrediction>(model);return predictionEngine;
}

3. 解析輸出結果

protected IEnumerable<ImageNetData> PredictDataUsingModel(string testLocation, string imagesFolder, string labelsLocation, PredictionEngine<ImageNetData, ImageNetPrediction> model)
{ConsoleWriteHeader("Classify images");Console.WriteLine($"Images folder: {imagesFolder}");Console.WriteLine($"Training file: {testLocation}");Console.WriteLine($"Labels file: {labelsLocation}");var labels = ReadLabels(labelsLocation);var testData = ImageNetData.ReadFromCsv(testLocation, imagesFolder);foreach (var sample in testData){var probs = model.Predict(sample).PredictedLabels;var imageData = new ImageNetDataProbability(){ImagePath = sample.ImagePath,Label = sample.Label};(imageData.PredictedLabel, imageData.Probability) = GetBestLabel(labels, probs);imageData.ConsoleWrite();yield return imageData;}
}

Main 方法中調用,完整代碼如下:

static void Main(string[] args)
{string assetsRelativePath = @"../../../assets";string assetsPath = GetAbsolutePath(assetsRelativePath);string tagsTsv = Path.Combine(assetsPath, "inputs", "images", "tags.tsv");string imagesFolder = Path.Combine(assetsPath, "inputs", "images");string inceptionPb = Path.Combine(assetsPath, "inputs", "inception", "tensorflow_inception_graph.pb");string labelsTxt = Path.Combine(assetsPath, "inputs", "inception", "imagenet_comp_graph_label_strings.txt");try{TFModelScorer modelScorer = new TFModelScorer(tagsTsv, imagesFolder, inceptionPb, labelsTxt);modelScorer.Score();}catch (Exception ex){ConsoleHelpers.ConsoleWriteException(ex.ToString());}ConsoleHelpers.ConsolePressAnyKey();
}

運行程序后,你將看到類似以下的輸出:


其他實現方式

在實際應用中,我們也可以使用ONNX模型,此處不做額外敘述。由于模型的性能和效率至關重要,只是提供一些優化建議:

  1. 模型量化:使用 ONNX Runtime 的量化工具,將模型從浮點數(FP32)轉換為整數(INT8),減少模型大小和推理時間。
  2. 硬件加速:結合 ONNX Runtime 的 GPU 支持,利用 CUDA 或 DirectML 加速推理。
  3. 批處理:如果需要處理多張圖像,可以將輸入組織為批次(batch),提高吞吐量。例如:
var inputs = new List<ImageInput> { input1, input2, input3 };
var batchPrediction = mlContext.Data.LoadFromEnumerable(inputs);
var predictions = model.Transform(batchPrediction);
  1. 緩存機制:對于頻繁使用的模型,保持預測引擎的單例實例,避免重復加載。

通過這些優化,模型可以在 .NET 環境中實現更高的性能,滿足實時應用的需求。


實際應用場景

圖像分類模型在 .NET 應用中有廣泛的用途,以下是幾個典型場景:

  1. 醫療影像分析
    在醫療系統中,部署圖像分類模型可以輔助醫生識別 X 光片或 MRI 圖像中的異常。例如,檢測肺部結節或腫瘤。

  2. 智能安防
    在監控系統中,模型可以實時識別可疑物體或行為,如檢測闖入者或遺留物品。

  3. 電子商務
    在商品管理系統中,自動分類上傳的商品圖像,提升搜索和推薦的準確性。

挑戰與解決方案

  • 數據隱私:通過加密傳輸和本地推理保護用戶數據。
  • 模型更新:定期從云端下載新模型,并使用版本控制管理。
  • 計算資源:在資源受限的設備上,使用輕量化模型(如 MobileNet)。

結論

本文詳細介紹了如何在 .NET 環境下使用 C# 部署和調用 AI 圖像分類模型。從環境搭建到模型選擇、部署與調用,再到性能優化和應用場景,我們提供了一套完整的實踐指南。通過 ML.NET 和預測模式的支持,開發者可以輕松地將強大的 AI 能力集成到 .NET 應用中。

隨著 AI 技術的不斷進步和 .NET 平臺的持續發展,二者的結合將為開發者帶來更多可能性。無論是構建智能桌面應用、Web 服務還是跨平臺解決方案,圖像分類模型都能為項目增添創新價值。希望本文能為你的 AI 之旅提供啟發和幫助!


參考資料

  • 素材下載地址: https://storage.googleapis.com/download.tensorflow.org/models/inception5h.zip
  • Netron工具地址: https://netron.app/
  • 224x224圖像素材: https://www.kaggle.com/datasets/abhinavnayak/catsvdogs-transformed/data
  • tensorflow教程及模型文件和label文件: https://github.com/martinwicke/tensorflow-tutorial
  • Image Classification - Scoring sample: https://github.com/dotnet/machinelearning-samples/blob/main/samples/csharp/getting-started/DeepLearning_ImageClassification_TensorFlow/README.md
  • ML.NET 官方文檔: https://dotnet.microsoft.com/apps/machinelearning-ai/ml-dotnet
  • ONNX Model Zoo: https://github.com/onnx/models

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/web/80930.shtml
繁體地址,請注明出處:http://hk.pswp.cn/web/80930.shtml
英文地址,請注明出處:http://en.pswp.cn/web/80930.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

Cause: org.apache.ibatis.ognl.OgnlException: sqlSegment

17:12:47.358 [http-nio-11080-exec-2] ERROR c.c.f.w.e.GlobalExceptionHandler - [handleRuntimeException,100] - 請求地址/xx/xxx/xxx/xxx/xxx/8bbe5b132a7a4d9bb28cedfeac94d69f,發生未知異常. org.mybatis.spring.MyBatisSystemException: nested exception is org.apach…

jmeter登錄接口生成一批token并寫入csv文件

背景&#xff1a;大部分項目真實的業務接口都是需要token鑒權的&#xff0c;想對一批核心業務接口進行并發壓測&#xff0c;必然要先生成一批token給這些接口并發循環調用。 基本的思路是這樣的&#xff1a;一批手機號csv文件 -》登錄接口循環讀取csv文件并生成token -》每次…

技術篇-2.3.Golang應用場景及開發工具安裝

Golang 雖然語法簡潔&#xff0c;上手也較快&#xff0c;但其在高并發、微服務和云原生領域的優勢明顯&#xff0c;要真正精通并靈活運用仍需積累大量實踐經驗。與 Java 借助重量級框架不同&#xff0c;Go 傾向于使用標準庫和輕量級第三方包來構建高性能、低延遲的系統。 1.1應…

Java面試問題基礎篇

面向對象 面向對象編程&#xff1a;拿東西過來做對應的事情 特征&#xff1a; 封裝&#xff1a;對象代表什么&#xff0c;就要封裝對應的數據&#xff0c;并提供數據對應的行為 繼承&#xff1a;Java中提供一個關鍵字extends&#xff0c;用這個關鍵字可以讓一個類和另一個類…

SpringBoot的前世今生

1. Spring Spring 特性&#xff1a;IOC、AOP、DI&#xff0c; Spring&#xff1a;解決對象耦合的問題&#xff0c;在 applicationContext.xml 中申明 bean&#xff0c;Spring在啟動時會解析xml文件進行裝載&#xff0c;當需要用對象時直接從容器中拿取bean。 Spring萬能膠&a…

微信小程序自行diy選擇器有效果圖

效果圖 實現思路 主要運用到小程序自帶視圖容器《swiper》 運用到的屬性《vertical》《display-multiple-items》《current》《animationfinish》 滑動方向變為縱向 vertical&#xff1a;true 顯示的滑塊數量 display-multiple-items&#xff1a;5 當前所在滑塊的 index curr…

【實用教程】如何快速搭建一套私有的埋點系統?

這篇教程將基于開源項目-ClkLog&#xff0c;教大家快速搭建一套自有的埋點系統&#xff0c;從0開始完成數據采集、分析與展示&#xff0c;全流程掌控用戶行為數據。 ClkLog是一款支持私有化部署的全開源用戶行為數據采集與分析系統&#xff0c;兼容Web、App、小程序多端埋點&am…

falsk模型-flask_sqlalchemy增刪改查

1、增、刪、改 增 home_bp.route(/useradd) def user_add():users []for i in range(10,20):user User()user.name 冰冰 str(i)user.age 20iusers.append(user)try:db.session.add_all(users)db.session.commit()return jsonify({code:1,info:success})except Exception…

【專題】機器學習期末復習資料

機器學習期末復習資料&#xff08;題庫&#xff09; 鏈接&#xff1a;https://blog.csdn.net/Pqf18064375973/article/details/148105494?sharetypeblogdetail&sharerId148105494&sharereferPC&sharesourcePqf18064375973&sharefrommp_from_link 【測試】 Art…

SpringCloud Alibaba微服務-- Sentinel的使用(筆記)

雪崩問題&#xff1a; 小問題引發大問題&#xff0c;小服務出現故障&#xff0c;處理不當&#xff0c;可能導致整個微服務宕機。 假如商品服務出故障&#xff0c;購物車調用該服務&#xff0c;則可能出現處理時間過長&#xff0c;如果一秒幾十個請求&#xff0c;那么處理時間過…

5:OpenCV—圖像亮度、對比度變換

1.更改圖像和視頻的亮度 更改亮度 更改圖像的亮度是常用的點操作。在此操作中&#xff0c;圖像中每個像素的值應增加/減少一個常數。要更改視頻的亮度&#xff0c;應對視頻中的每一幀執行相同的操作。 如果要增加圖像的亮度&#xff0c;則必須為圖像中的每個像素添加一些正常…

【工作流】Fastgpt配置豆包模型-火山引擎

V4.9.7 Fastgpt現在不通過oneapi 來配置模型和渠道了&#xff0c; 可以直接在頁面進行設置 首先在賬號- 模型提供商里面 填入豆包的信息&#xff1a; 渠道名隨便填&#xff0c;廠商選豆包&#xff0c; 然后選3個模型&#xff0c;如圖所示 如果沒有填入模型映射的話是沒辦法 …

2025年系統架構師---綜合知識卷

1.進程是一個具有獨立功能的程序關于某數據集合的一次運行活動,是系統進行資源分配和調度的基本單位(線程包含于進程之中,可并發,是系統進行運算調度的最小單位)。一個進程是通過其物理實體被感知的,進程的物理實體又稱為進程的靜態描述,通常由三部分組成,分別是程序、…

LangChain4j入門AI(六)整合提示詞(Prompt)

前言 提示詞&#xff08;Prompt&#xff09;是用戶輸入給AI模型的一段文字或指令&#xff0c;用于引導模型生成特定類型的內容。通過提示詞&#xff0c;用戶可以告訴AI“做什么”、 “如何做”以及“輸出格式”&#xff0c;從而在滿足需求的同時最大程度減少無關信息的生成。有…

如何使用 Docker Compose 部署 Immich

如何使用 Docker Compose 部署 Immich Immich 是一個開源的自建照片和視頻備份解決方案&#xff0c;通過 Docker 部署可以快速構建一個穩定的自主管理系統。本文將帶你一步步完成使用 Docker Compose 部署 Immich 的過程&#xff0c;幫助你在生產環境中實現高效的媒體管理。 1…

Mac遠程連接Windows電腦教程

在 Mac 上通過微軟官方遠程桌面工具&#xff08;Windows App&#xff09;連接局域網內的 Windows 電腦&#xff0c;需按照以下步驟操作&#xff1a; 一、準備工作 確認 Windows 版本支持遠程連接 Windows 專業版/企業版/教育版 支持遠程桌面功能。家庭版不支持&#xff0c;需使…

從0到1打造AI Copilot:用SpringBoot + ChatGPT API實現智能開發助手

本文將從0到1系統性地講解如何基于SpringBoot與OpenAI ChatGPT API打造一款智能開發助手&#xff08;AI Copilot&#xff09;。文章首先介紹AI Copilot的背景與價值&#xff0c;接著深入架構設計與環境準備&#xff0c;然后通過詳盡的代碼示例演示SpringBoot項目的搭建、依賴配…

Crawl4AI:高效的AI數據抓取工具

在大數據時代&#xff0c;抓取并處理大量數據是進行人工智能&#xff08;AI&#xff09;研究與開發的基礎。而網絡爬蟲是獲取網頁數據的重要工具。今天&#xff0c;我想介紹一個功能強大的爬蟲框架——Crawl4AI&#xff0c;它為數據抓取和機器學習任務提供了無縫的支持。Crawl4…

從單鏈表 list 中刪除第 i 個元素--Python

從單鏈表 list 中刪除第 i 個元素 一、問題引入二、解題步驟1.思維導圖2.解題步驟 三、代碼實現四、個人總結 一、問題引入 請編寫程序&#xff0c;將 n 個整數順次插入一個初始為空的單鏈表的表頭。隨后對任意給定的位序 i&#xff0c;刪除鏈表中第 i 個結點。注意&#xff1…

git學習與使用(遠程倉庫、分支、工作流)

文章目錄 前言簡介git的工作流程git的安裝配置git環境&#xff1a;git config --globalgit的基本使用新建目錄初始化倉庫&#xff08;repository&#xff09;添加到暫存區新增/修改/刪除 文件狀態會改變 提交到倉庫查看提交&#xff08;commit&#xff09;的歷史記錄git其他命令…