iT邦幫忙

2025 iThome 鐵人賽

DAY 8
0
Rust

30天解鎖 Rust 開發者工具箱系列 第 8

「Day 08」用 ort 打造 AI 物件辨識應用(一)

  • 分享至 

  • xImage
  •  

https://ithelp.ithome.com.tw/upload/images/20250922/20177832qXot1oMXLV.jpg
圖:“Rust 的吉祥物 Ferris the Crab 透過 ort 搭建起 Rust 和 ONNX 之間的橋樑”,gemini-2.5-flash-preview,2025年09月22日。

前言

看著 Python 在 AI 領域獨領風騷,心想:「我什麼時候才能用我心愛的 Rust 來駕馭那些強大的神經網路模型呢?」

ort:我來解救你!

ort crate 正是 ONNX Runtime 的 Rust 綁定 (binding),它讓我們能用 Rust 的方式,安全、高效地呼叫 ONNX Runtime 引擎,執行來自 AI 世界的 ONNX 模型。今天,我們就跟著這位螃蟹技師,一步步搭建這座橋樑,並實際運行一個物件辨識(Object Detection)的應用程式!

實作範例

專案設定 - Cargo.toml 配置

[dependencies]
ort = { version = "1.16.3", features = ["download-binaries"] }

重要提示: ort crate 需要你的系統上安裝了 ONNX Runtime 函數庫。最簡單的方式是從 ONNX Runtime 的 GitHub Releases 下載對應你作業系統的預編譯版本,並將其解壓縮。接著,設定環境變數 ONNXRUNTIME_LIB_DIR 指向函式庫所在的 lib 資料夾。

步驟一:ONNX 模型各式與資料準備

若從 Python 生態系過來嚐鮮的 AI 技術愛好者,相信以下操作一定再熟悉不過了,就是起手式!一樣的,我們要站在巨人的肩膀上,ultralytics 早已是 AI 生態系中相當成熟的 YOLO 電腦視覺模型函數庫。我們在接下來的 AI 應用中並不會訓練模型,我們將著重在推理的落地上,故第一步我們將利用 ultralytics 這一工具進行模型下載和驗證。

pip install -U ultralytics

然後,將所需的 YOLOv8/YOLO11 模型匯出為 ONNX 格式,詳細資訊請參閱 Model Export with Ultralytics YOLO

# 匯出具有動態形狀的 ONNX 模型(建議使用以提高靈活性)
yolo export model=yolo11s.pt format=onnx simplify dynamic
yolo export model=yolo11s-cls.pt format=onnx simplify dynamic
yolo export model=yolo11s-pose.pt format=onnx simplify dynamic
yolo export model=yolo11s-seg.pt format=onnx simplify dynamic

步驟二:確定 ONNX 模型導入成功

函數原始碼

/// 模型驗證函數,用於驗證 ONNX 模型載入和配置 (Model validation function to verify ONNX model loading and configuration)
fn validate_onnx_model(config: &config::Config) -> Result<(), Box<dyn std::error::Error>> {
    println!("🔍 驗證 ONNX 模型載入 (Validating ONNX Model Loading)");
    println!("========================");

    // 載入 YOLO 模型 (Load the YOLO model)
    println!("📦 載入模型 (Loading model): {}", config.model);
    let model = YOLOv8::new(config.clone())?;
    println!("✅ 模型載入成功! (Model loaded successfully!)");

    // 顯示模型資訊 (Display model information)
    println!("\n📊 模型資訊 (Model Information):");
    println!("   任務類型 (Task Type): {:?}", model.task);
    println!("   輸入尺寸 (Input Dimensions): {}x{}", model.width, model.height);
    println!("   批次大小 (Batch Size): {}", model.batch);
    println!("   類別數量 (Number of Classes - nc): {}", model.nc);
    println!("   關鍵點數量 (Number of Keypoints - nk): {}", model.nk);
    println!("   遮罩數量 (Number of Masks - nm): {}", model.nm);
    println!("   信心度閾值 (Confidence Threshold): {:.2}", model.conf);
    println!("   IoU 閾值 (IoU Threshold): {:.2}", model.iou);
    println!("   關鍵點信心度閾值 (Keypoint Confidence Threshold): {:.2}", model.kconf);

    // 顯示執行提供者 (Display execution provider)
    println!("\n⚡ 執行提供者 (Execution Provider):");
    println!("   提供者 (Provider): {:?}", model.engine.ep());

    // 顯示類別名稱(如果可用) (Display class names if available)
    if !model.names.is_empty() {
        println!("\n🏷️  類別名稱 (Class Names - {} classes):", model.names.len());
        for (i, name) in model.names.iter().enumerate() {
            if i < 10 { // 顯示前 10 個類別 (Show first 10 classes)
                println!("   {:2}: {}", i, name);
            } else if i == 10 {
                println!("   ... 還有 {} 個類別 (... and {} more classes)", model.names.len() - 10, model.names.len() - 10);
                break;
            }
        }
    } else {
        println!("\n🏷️  類別名稱 (Class Names): 模型元資料中無法取得 (Not available in model metadata)");
    }


    // 驗證模型後端資訊 (Verify model backend information)
    println!("\n🔧 後端配置 (Backend Configuration):");
    println!("   動態批次 (Dynamic Batch): {}", model.engine.is_batch_dynamic());
    println!("   動態高度 (Dynamic Height): {}", model.engine.is_height_dynamic());
    println!("   動態寬度 (Dynamic Width): {}", model.engine.is_width_dynamic());
    println!("   資料類型 (Data Type): {:?}", model.engine.dtype());

    Ok(())
}

預期輸出

🔍 驗證 ONNX 模型載入 (Validating ONNX Model Loading)
========================
📦 載入模型 (Loading model): model_weight/onnx/version/yolo11s.onnx
✅ 模型載入成功! (Model loaded successfully!)

📊 模型資訊 (Model Information):
   任務類型 (Task Type): Detect
   輸入尺寸 (Input Dimensions): 640x640
   批次大小 (Batch Size): 1
   類別數量 (Number of Classes - nc): 80
   關鍵點數量 (Number of Keypoints - nk): 0
   遮罩數量 (Number of Masks - nm): 0
   信心度閾值 (Confidence Threshold): 0.30
   IoU 閾值 (IoU Threshold): 0.45
   關鍵點信心度閾值 (Keypoint Confidence Threshold): 0.55

⚡ 執行提供者 (Execution Provider):
   提供者 (Provider): Cpu

🏷️  類別名稱 (Class Names - 80 classes):
    0: person
    1: bicycle
    2: car
    3: motorcycle
    4: airplane
    5: bus
    6: train
    7: truck
    8: boat
    9: traffic light
   ... 還有 70 個類別 (... and 70 more classes)

🔧 後端配置 (Backend Configuration):
   動態批次 (Dynamic Batch): true
   動態高度 (Dynamic Height): true
   動態寬度 (Dynamic Width): true
   資料類型 (Data Type): Float32

結語

今天太忙了!時間完全不夠用,先這樣!XD


上一篇
「Day 07」探索 AI 框架
下一篇
「Day 08」用 ort 打造 AI 物件辨識應用(二)
系列文
30天解鎖 Rust 開發者工具箱9
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言