在C#中如何使用ResNet50v2進(jìn)行圖像識(shí)別
ONNX Runtime簡(jiǎn)介
ONNX Runtime 是一個(gè)跨平臺(tái)的推理和訓(xùn)練機(jī)器學(xué)習(xí)加速器。ONNX 運(yùn)行時(shí)推理可以實(shí)現(xiàn)更快的客戶體驗(yàn)和更低的成本,支持來(lái)自深度學(xué)習(xí)框架(如 PyTorch 和 TensorFlow/Keras)以及經(jīng)典機(jī)器學(xué)習(xí)庫(kù)(如 scikit-learn、LightGBM、XGBoost 等)的模型。 ONNX 運(yùn)行時(shí)與不同的硬件、驅(qū)動(dòng)程序和操作系統(tǒng)兼容,并通過(guò)利用硬件加速器(如果適用)以及圖形優(yōu)化和轉(zhuǎn)換來(lái)提供最佳性能。

ResNet50v2簡(jiǎn)介
ResNet50v2 是一種深度卷積神經(jīng)網(wǎng)絡(luò)架構(gòu),是 ResNet(Residual Network,殘差網(wǎng)絡(luò))系列的一部分。ResNet 是由何凱明等人在 2015 年提出的,它通過(guò)引入殘差塊(Residual Block)解決了深度神經(jīng)網(wǎng)絡(luò)訓(xùn)練過(guò)程中梯度消失和梯度爆炸的問(wèn)題,使得構(gòu)建非常深的網(wǎng)絡(luò)成為可能。ResNet50v2 被廣泛應(yīng)用于各種計(jì)算機(jī)視覺(jué)任務(wù),如圖像分類、目標(biāo)檢測(cè)、圖像分割等。由于其深度和強(qiáng)大的特征學(xué)習(xí)能力,ResNet50v2 在眾多基準(zhǔn)測(cè)試中表現(xiàn)出色,是許多研究和應(yīng)用中的首選模型之一。
示例
這個(gè)示例代碼在
fork一份,克隆到本地,在本地打開(kāi)這個(gè)項(xiàng)目,項(xiàng)目結(jié)構(gòu)如下所示:

依賴的包除了OnnxRuntime還有ImageSharp。
ImageSharp簡(jiǎn)介
ImageSharp 是一個(gè)新的、功能齊全、完全托管的跨平臺(tái) 2D 圖形庫(kù)。ImageSharp 旨在簡(jiǎn)化圖像處理,為您帶來(lái)一個(gè)非常強(qiáng)大而又非常簡(jiǎn)單的 API。
ImageSharp 從頭開(kāi)始設(shè)計(jì),具有靈活性和可擴(kuò)展性。該庫(kù)為常見(jiàn)的圖像處理操作提供了 API 端點(diǎn),并為開(kāi)發(fā)其他操作提供了構(gòu)建塊。
ImageSharp 針對(duì) .NET 8 構(gòu)建,可用于設(shè)備、云和嵌入式/IoT 方案。

下載 ResNet50 v2 ONNX 模型,下載地址在:
讀取路徑
首先,源代碼中是通過(guò)程序參數(shù)讀取模型的路徑和要測(cè)試的圖像的路徑,也可以直接賦值:
// Read paths //string modelFilePath = args[0]; //string imageFilePath = args[1]; string modelFilePath = @"你的路徑\Microsoft.ML.OnnxRuntime.ResNet50v2Sample\resnet50-v2-7.onnx"; string imageFilePath = @"你的路徑\Microsoft.ML.OnnxRuntime.ResNet50v2Sample\獅子.jpg";
讀取圖像
接下來(lái),我們將使用跨平臺(tái)圖像庫(kù) ImageSharp 讀取圖像:
// Read image using Image<Rgb24> image = Image.Load<Rgb24>(imageFilePath);
調(diào)整圖像大小
接下來(lái),我們將圖像大小調(diào)整為模型期望的適當(dāng)大小;224 像素 x 224 像素:
using Stream imageStream = new MemoryStream();
image.Mutate(x =>
{
x.Resize(new ResizeOptions
{
Size = new Size(224, 224),
Mode = ResizeMode.Crop
});
});
image.Save(imageStream, format);預(yù)處理圖像
接下來(lái),我們將根據(jù)模型的要求對(duì)圖像進(jìn)行預(yù)處理,具體要求見(jiàn):
https://github.com/onnx/models/tree/main/validated/vision/classification/resnet
// We use DenseTensor for multi-dimensional access to populate the image data
var mean = new[] { 0.485f, 0.456f, 0.406f };
var stddev = new[] { 0.229f, 0.224f, 0.225f };
DenseTensor<float> processedImage = new(new[] { 1, 3, 224, 224 });
image.ProcessPixelRows(accessor =>
{
for (int y = 0; y < accessor.Height; y++)
{
Span<Rgb24> pixelSpan = accessor.GetRowSpan(y);
for (int x = 0; x < accessor.Width; x++)
{
processedImage[0, 0, y, x] = ((pixelSpan[x].R / 255f) - mean[0]) / stddev[0];
processedImage[0, 1, y, x] = ((pixelSpan[x].G / 255f) - mean[1]) / stddev[1];
processedImage[0, 2, y, x] = ((pixelSpan[x].B / 255f) - mean[2]) / stddev[2];
}
}
});在這里,我們正在創(chuàng)建一個(gè)所需大小 (batch-size, channels, height, width) 的張量,訪問(wèn)像素值,對(duì)其進(jìn)行預(yù)處理,最后將它們分配給適當(dāng)指示的張量。
設(shè)置輸入
接下來(lái),我們將創(chuàng)建模型的輸入:
using var inputOrtValue = OrtValue.CreateTensorValueFromMemory(OrtMemoryInfo.DefaultInstance,
processedImage.Buffer, new long[] { 1, 3, 224, 224 });
var inputs = new Dictionary<string, OrtValue>
{
{ "data", inputOrtValue }
}要檢查 ONNX 模型的輸入節(jié)點(diǎn)名稱,您可以使用 Netron 可視化模型并查看輸入/輸出名稱。在本例中,此模型具有 data 作為輸入節(jié)點(diǎn)名稱。
運(yùn)行推理
接下來(lái),我們將創(chuàng)建一個(gè)推理會(huì)話并通過(guò)它運(yùn)行輸入:
using var session = new InferenceSession(modelFilePath); using var runOptions = new RunOptions(); using IDisposableReadOnlyCollection<OrtValue> results = session.Run(runOptions, inputs, session.OutputNames);
后處理輸出
接下來(lái),我們需要對(duì)輸出進(jìn)行后處理以獲得 softmax 向量,因?yàn)檫@不是由模型本身處理的:
var output = results[0].GetTensorDataAsSpan<float>().ToArray(); float sum = output.Sum(x => (float)Math.Exp(x)); IEnumerable<float> softmax = output.Select(x => (float)Math.Exp(x) / sum);
其他型號(hào)可能會(huì)在輸出之前應(yīng)用 Softmax 節(jié)點(diǎn),在這種情況下,您不需要此步驟。同樣,您可以使用 Netron 查看模型輸出。
提取前10個(gè)預(yù)測(cè)結(jié)果
IEnumerable<Prediction> top10 = softmax.Select((x, i) => new Prediction { Label = LabelMap.Labels[i], Confidence = x })
.OrderByDescending(x => x.Confidence)
.Take(10);打印結(jié)果
Console.WriteLine("Top 10 predictions for ResNet50 v2...");
Console.WriteLine("--------------------------------------------------------------");
foreach (var t in top10)
{
Console.WriteLine($"Label: {t.Label}, Confidence: {t.Confidence}");
}
本例的示例圖片是一只獅子,如下所示:

查看預(yù)測(cè)結(jié)果:

在LabelMap類中可以查看該模型可以識(shí)別的物體:

例如cock是公雞的意思,我們可以現(xiàn)場(chǎng)找一張公雞的圖片,查看效果。
找到的一張公雞圖片如下所示:

修改測(cè)試圖片為這種圖片,再次運(yùn)行,結(jié)果如下所示:

成功識(shí)別出了公雞。
總結(jié)
以上就完成了ONNX Runtime的入門(mén)示例,可以根據(jù)興趣與需求嘗試使用其他的模型。
參考
1、Image recognition with ResNet50v2 in C# | onnxruntime
4、SixLabors/ImageSharp: ?? A modern, cross-platform, 2D Graphics library for .NET (github.com)
到此這篇關(guān)于在C#中使用ResNet50v2進(jìn)行圖像識(shí)別的文章就介紹到這了,更多相關(guān)C# ResNet50v2圖像識(shí)別內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
BootStrap mvcpager分頁(yè)樣式(get請(qǐng)求,刷新頁(yè)面)
這篇文章主要介紹了BootStrap mvcpager分頁(yè)樣式(get請(qǐng)求,刷新頁(yè)面)的相關(guān)資料,通過(guò)引入相關(guān)文件,實(shí)現(xiàn)此功能,非常不錯(cuò),具有參考借鑒價(jià)值,需要的朋友可以參考下2016-08-08
c#實(shí)現(xiàn)圖片的平移和旋轉(zhuǎn)示例代碼
這篇文章主要給大家介紹了關(guān)于c#實(shí)現(xiàn)圖片的平移和旋轉(zhuǎn)的相關(guān)資料,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家學(xué)習(xí)或者使用c#具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2019-08-08
C#代碼實(shí)現(xiàn)刪除Excel中的重復(fù)行
在日常數(shù)據(jù)處理中,Excel?表格中的重復(fù)行是一個(gè)常見(jiàn)問(wèn)題,本文將詳細(xì)介紹如何使用?Free?Spire.XLS?for?.NET,通過(guò)?C#?代碼以編程方式刪除?Excel?工作表中的重復(fù)行,有需要的小伙伴可以了解下2026-05-05
用幾行C#代碼實(shí)現(xiàn)定時(shí)關(guān)機(jī)/重啟(超詳細(xì)!建議新手練習(xí))
有很多的軟件都實(shí)現(xiàn)了自動(dòng)關(guān)機(jī)這樣的功能,下面這篇文章主要給大家介紹了關(guān)于利用幾行C#代碼實(shí)現(xiàn)定時(shí)關(guān)機(jī)/重啟的相關(guān)資料,文中通過(guò)圖文介紹的非常詳細(xì),需要的朋友可以參考下2022-12-12
.NET/C#實(shí)現(xiàn)識(shí)別用戶訪問(wèn)設(shè)備的方法
這篇文章主要介紹了.NET/C#實(shí)現(xiàn)識(shí)別用戶訪問(wèn)設(shè)備的方法,結(jié)合實(shí)例形式分析了C#識(shí)別用戶訪問(wèn)設(shè)備的操作技巧,具有一定參考借鑒價(jià)值,需要的朋友可以參考下2017-02-02
C#ComboBox控件“設(shè)置 DataSource 屬性后無(wú)法修改項(xiàng)集合”的解決方法
這篇文章主要介紹了C#ComboBox控件“設(shè)置 DataSource 屬性后無(wú)法修改項(xiàng)集合”的解決方法 ,需要的朋友可以參考下2019-04-04

