---
# System prepended metadata

title: '如何用 SAHI 偵測小物件：推論與微調 --- How to Detect Small Objects with SAHI: Inference & Fine-Tuning'

---

# 如何用 SAHI 偵測小物件：推論與微調
# How to Detect Small Objects with SAHI: Inference & Fine-Tuning

> 原文來源：https://visionbrick.com/how-to-detect-small-objects-with-sahi-inference-fine-tuning/

---

像 Ultralytics 這類函式庫對深度學習，特別是物件偵測，有很大影響。即使一個人對電腦視覺一無所知，他們也能透過結合幾個元素來訓練並部署物體偵測模型。首先，從 Kaggle 找到資料集，建立筆記本，啟用 GPU，然後用 Ultralytics 來訓練。只要寫近 **50 行程式碼**，花 **4 到 5 小時**，**任何人都能訓練 YOLO 模型並部署**。是的，這對一般物體偵測是有效的。如果資料集夠乾淨且夠大，就會有一個模型能在大多數情況下使用。你大多時候可以準確偵測常見物體，比如汽車、人。但這是每個任務都一樣嗎？


![Small Object Detection with SAHI](https://hackmd.io/_uploads/H1vO69yQ-e.png)

**Small Object Detection with SAHI [VisDrone19-Detection dataset]**
使用 SAHI 進行小型物體偵測 [VisDrone19-Detection 資料集]

當然不，我們來想想小物件。物體太小，甚至用肉眼無法準確辨識。因此，這種簡單的方法行不通，針對**小型物體的偵測有不同的解決方案**，本文將介紹 **SAHI**。SAHI 的主要理念是將影像切片成較小的區域，並在這些小區域進行推論與訓練，並進一步處理。

---

## 為什麼小物件偵測較難？SAHI 如何成功？

想像影像中的小物體，如飛機、昆蟲和遠方的人。即使在原始圖片中，也很難辨認。現在想想模型訓練部分，因為記憶體限制和訓練時間，大多數情況下**影像會被調整到像 640×640、640×480 這樣的解析度**。

即使在預設情況下，Ultralytics 也會將原始圖片調整為 640×640。影像大小會顯著影響訓練時間，有時在低 GPU VRAM（4GB、6GB、8GB）時，**CUDA 記憶體不足**錯誤很常見。你可以透過減少批次大小或影像解析度來解決這個問題。

![How SAHI Slicing Aided Inference works](https://visionbrick.com/wp-content/uploads/2025/11/sahichart-3-1024x647.png.webp)
**How SAHI Slicing Aided Inference works?**
SAHI 切片輔助推論是如何運作的？

物件即使在原始解析度下也很小，想想在訓練前調整大小後會發生什麼事？它們變得**非常小**，有時甚至消失。這時 SAHI 登場了。這個想法簡單卻有效：如果我們**將影像切成較小的片段**，逐個處理，就不必將整張影像調整到較低解析度。將影像切片成多個片段後，每個片段的尺寸調整到較高解析度，同時保持比例，使**較小的區域變大**（同時物體變大），此方法對小物件偵測有顯著效果。

![Detecting Small Objects with SAHI](https://visionbrick.com/wp-content/uploads/2025/11/image-31.png.webp)
**Detecting Small Objects with SAHI [VisDrone19-Detection dataset]**
使用 SAHI 偵測小型物體 [VisDrone19-Detection 資料集]

如果你有時間，我強烈建議你閱讀 SAHI 的論文。內容不長（4 頁），而且他們解釋得很完美。你可以從[這裡](https://arxiv.org/abs/2202.06934)閱讀。

---

## SAHI (Slicing Aided Hyper Inference)
SAHI（切割輔助超推論）

你可以在任何物件偵測模型上使用 SAHI，因為**它不會改變模型架構**。其理念是將影像切片成較小的區域；因此，模型架構保持不變。你可以搭配 **YOLO**、**Faster R-CNN**、**SSD**、**DETR** 等任何你想到的物體偵測模型。

如我之前所說，影像會被切成較小的區域，每個區域都分別處理。但有一個問題：**如果一個物件夾在兩個補丁之間呢？** 解決這個問題，每個補丁與相鄰補丁重疊 **25%**。最後，為了消除從相鄰補丁偵測到的重複物件，會應用 **NMS（非最大抑制）**。順帶一提，25% 是預設參數；你可以改變它。

![Object falls between two patches](https://visionbrick.com/wp-content/uploads/2025/11/overlap-1024x746.png.webp)
**Object falls between two patches**
物體落在兩個區域之間 [[img](https://www.pexels.com/photo/person-hiking-in-mountains-13416295/)]

論文中提出了兩種不同的方法：

### 1. Slicing Aided Inference（切割輔助推論）

到目前為止，我已經告訴你第一個方法的主要概念，但還有更多。好，我們有一張圖片，然後把它切成更小的區域。重要的是把這些較小的補丁**調整到更高解析度**。透過這樣做，我們的小塊會變大，裡面的物體也會變大。接著，物件偵測模型會運行在這些新產生的高解析度補丁上。對於小型物體，這種方法特別合理，尤其是**高解析度影像中的小物體**。

![Slicing Aided Inference](https://visionbrick.com/wp-content/uploads/2025/11/image-12.png.webp)
**Slicing Aided Inference**. Source: [[paper link](https://arxiv.org/abs/2202.06934)]
切割輔助推論

### 2. Slicing Aided Fine-tuning（切割輔助微調）

那「切割輔助微調」方法呢？顧名思義，這是關於訓練。訓練前，將影像切片成較小的片段，將這些片段調整至較大解析度，然後**在這些新建立的高解析度片段及整張影像上訓練物件偵測模型**。你可以直覺地處理這件事，因為這很有道理。你有一個超小的物體，存在於高解析度影像中。首先，你將這張圖片分割成較小的區域，然後將這些小區域調整到更高解析度。這樣一來，你的超小物體會變大，接著你用這些補丁訓練物體偵測模型，讓**小物體偵測的準確度提升**。

![Slicing Aided Fine-tuning](https://visionbrick.com/wp-content/uploads/2025/11/image-11.png.webp)
**Slicing Aided Fine-tuning**. Source: [[paper link](https://arxiv.org/abs/2202.06934)]
切割輔助微調

現在，我將展示論文中建議的兩種方法的示範。首先，我會示範如何**將 YOLO 模型與 SAHI 結合**，以提升小物件偵測的推論能力。接下來，我將示範如何在你的資料集上進行**切片輔助微調**，以訓練更穩健的小型物件偵測模型。

---

## 安裝 Installation

安裝並不複雜；你需要幾個函式庫。你應該建立一個支援 GPU 的 PyTorch 環境來訓練並加快推論速度。

```bash
pip install sahi
```

![GitHub repository of SAHI](https://visionbrick.com/wp-content/uploads/2025/11/image-32-1024x575.png.webp)
**GitHub repository of SAHI** ([link](https://github.com/obss/sahi))
SAHI 的 GitHub 倉庫

---

## 1. Slicing Aided Inference with YOLO + SAHI
以 YOLO + SAHI 切割輔助推論

好，讓我們從切片輔助推論開始。我談了很多事情，比如調整圖片大小到低解析度或高解析度、重疊區域。**我們不需要處理這些問題，因為 SAHI 和 Ultralytics 一樣使用者友善**。

![Slicing Aided Inference with YOLO + SAHI](https://visionbrick.com/wp-content/uploads/2025/11/image-13.png.webp)
**Slicing Aided Inference with YOLO + SAHI**
與 YOLO + SAHI 的輔助推斷切割

首先，建立一個 `UltralyticsDetectionModel` 類別實例來**載入你的 YOLO 模型**，然後用 `get_sliced_prediction` 函式來**推論**。我用的是預訓練的 YOLO 模型（`yolov8n.pt`）。如果你想用自訂模型或其他預訓練模型來使用 SAHI，情況不會改變。

`UltralyticsDetectionModel`（models/ultralytics.py）繼承自 `DetectionModel`（models/base.py）類別。我強烈建議你查閱原始碼以更好理解。

![models structure](https://visionbrick.com/wp-content/uploads/2025/11/image-14.png.webp)
**models/ultralytics.py, models/base.py**

你可以在 `predict.py` 檔案中找到 `get_sliced_prediction` 函式所需的所有資訊。

![get_sliced_prediction function](https://visionbrick.com/wp-content/uploads/2025/11/image-15.png.webp)
**`get_sliced_prediction` function inside `predict.py` file**

現在讓我們來推論 SAHI。你可以更改 `model_path`、`device`，以及測試影像的路徑。

參數說明：
- **slice_height**：補丁高度
- **slice_width**：補丁的寬度
- **overlap_ratio**：相鄰補丁的重疊百分比

```python
from sahi.models.ultralytics import UltralyticsDetectionModel
from sahi.predict import get_sliced_prediction

detection_model = UltralyticsDetectionModel(
    model_path="yolov8n.pt",
    confidence_threshold=0.3,
    device="cuda"
)

result = get_sliced_prediction(
    r"images/cars.jpg",
    detection_model,
    slice_height=256,
    slice_width=256,
    overlap_height_ratio=0.2,
    overlap_width_ratio=0.2
)
```

![Detection of small objects with SAHI](https://visionbrick.com/wp-content/uploads/2025/11/vertical_comparison-734x1024.jpg.webp)
**Detection of small objects with SAHI** [[img](https://www.pexels.com/photo/road-between-green-leafed-trees-59512/)]
用 SAHI 偵測小物體

### 視覺化結果

為了視覺化結果，你可以循環 `result` 變數，取得包圍框座標、標籤資訊和置信度值，然後畫出包圍框並在物件上寫入標籤資訊。或者，你也可以直接使用 `export_visuals` 函數；它會將輸出影像儲存到 `export_dir` 路徑。

```python
for pred in result.object_prediction_list:
    bbox = pred.bbox.to_xyxy()
    x1, y1, x2, y2 = map(int, bbox)
    label = pred.category.name
    score = pred.score.value
```

```python
result.export_visuals(export_dir="runs/predictions/")
```

### slice_image 函式

還有另一個很酷的函數叫 `slice_image`。你可以利用這個功能**儲存所有切片**，以更好地視覺化和理解 SAHI。讓我給你看一個簡短的示範。

```python
from sahi.slicing import slice_image

slice_image_result = slice_image(
    image="test_image.jpg",
    output_file_name="slice",
    output_dir="runs/sliced_images/",
    slice_height=256,
    slice_width=256,
    overlap_height_ratio=0.2,
    overlap_width_ratio=0.2,
)

print(f"Original Image Size: {slice_image_result.original_image_height}x{slice_image_result.original_image_width} (HxW)")
print(f"Slice Size: {slice_width}x{slice_height} pixels")
print(f"Total Slices Created: {len(slice_image_result.images)}")
print(f"Slices Saved To: {slice_image_result.image_dir}")
```

輸出結果：
- Original Image Size: **853×1280 (HxW)**
- Slice Size: **256×256 pixels**
- Total Slices Created: **24 Slices**
- Saved To: **runs/sliced_images/**

![Sliced images output](https://visionbrick.com/wp-content/uploads/2025/11/image-16-1024x443.png.webp)
**Output: Sliced images in the `output_dir` directory**
輸出：`output_dir` 目錄中的切片影像

---

## 2. Slicing Aided Fine-tuning
切割輔助微調

現在是第二部分的時間。這個想法和第一個很接近；**主要差別在於此步驟是在訓練階段之前完成，而非推論時**。假設我們有一個包含 **1,000** 張高解析度影像的資料集。首先，像第一種方法一樣將影像切成片段，然後再放大。用這些放大後的補丁來訓練物件偵測模型。根據切片參數和影像大小，你會有大約 **10,000** 到 **50,000** 張訓練影像。

**當你擁有高解析度資料集時，這種方法會有效**。假設你的資料集包含低解析度影像，例如 640×640。所以，切割就沒有意義；影像解析度本來就很低。所以，如果你的影像解析度很高，比如 **1920×1080**、**2160×1440** 等，最好進行微調。

### VisDrone19-Detection Dataset

我會用 **VisDrone19-Detection Dataset** 做微調，因為論文中的基準測試都是在這個資料集上進行的。該資料集包含由無人機拍攝的高解析度影像。

![Benchmark results](https://visionbrick.com/wp-content/uploads/2025/11/image-17.png.webp)
**Benchmark results on VisDrone19-Detection dataset**. Source: [[paper link](https://arxiv.org/abs/2202.06934)]
VisDrone19-Detection 資料集上的基準測試結果

資料集包含不同解析度，如 **1400×1050**、**1920×1080** 及 **2000×1500** 高解析度影像。我決定只用 **2000×1500** 張圖片，因為切片會大幅增加圖片數量，而且我的 GTX 1660 Ti Max-Q GPU 訓練兩天後可能會燒毀 :/

![Visdrone19-Detection dataset](https://visionbrick.com/wp-content/uploads/2025/11/visdrone-example-images-1024x783.png.webp)
**Visdrone19-Detection dataset**
Visdrone19-Detection 資料集

您可以在下方圖表中看到該 VisDrone19-Detection 資料集的影像解析度分布。

![Image resolution distribution](https://visionbrick.com/wp-content/uploads/2025/11/visdrone_size_distribution-1024x434.png.webp)
**Image resolution distribution of the VisDrone19-Detection dataset**
VisDrone19-Detection 資料集的影像解析度分布

### 資料集格式轉換

VisDrone19-Detection 資料集格式並非 COCO 格式。如果你不想花時間把資料集轉換成 COCO 格式，我建議你**直接選擇已經是 COCO 格式的資料集**。我處理了 VisDrone19-Detection 資料集並匯出成 COCO 格式。

![Converting to YOLO format](https://visionbrick.com/wp-content/uploads/2025/11/image-24.png.webp)
**Converting VisDrone19-Detection dataset to YOLO format**
將 VisDrone19-Detection 資料集轉換為 YOLO 格式

### slice_coco 函式

在 SAHI 中，有一個稱為 `slice_coco` 的函數。這個函式會將 COCO 格式的資料集切片，然後建立 COCO 格式的資料集。

你可以改變 `coco_annotation_path`、`image_dir`、`output_dir` 變數。

```python
from sahi.slicing import slice_coco

coco_dict, coco_path = slice_coco(
    coco_annotation_file_path=coco_annotation_path,
    image_dir=IMAGE_DIR,
    output_coco_annotation_file_name="visdrone_train_sliced.json",
    output_dir=SLICED_OUTPUT_DIR,
    ignore_negative_samples=False,
    slice_height=640,
    slice_width=640,
    overlap_height_ratio=0.2,
    overlap_width_ratio=0.2,
    min_area_ratio=0.1,
    verbose=True
)
```

輸出是一個包含所有圖片的資料夾，以及一個 JSON 格式的註解檔案。你可以在 `output_coco_annotation_file_name` 目錄裡看到註解檔，以及 `output_dir` 目錄下的切片圖片。

當你擁有 COCO 格式的資料集後，一切都變得相當簡單。COCO 格式就像深度學習中的 `print("hello world")`。你可以用各種工具匯出不同的資料集格式，但我覺得沒必要。你可以直接建立一條簡單的管線，從 COCO 格式匯出到任何其他格式。

我要訓練一個 YOLO 模型；因此，我將資料集轉換成 YOLO 格式。

> VisDrone19-Detection dataset → COCO format → YOLO format

![Example YOLO format](https://visionbrick.com/wp-content/uploads/2025/11/image-25.png.webp)
**Example YOLO format**
YOLO 格式範例

你可以將資料集拆分成訓練集和驗證集，比例隨你所想。你可以從 `slice_coco` 函式建立的切片資料集中看到幾個範例。

![Visdrone19-Detection dataset with annotations](https://visionbrick.com/wp-content/uploads/2025/11/visdrone_sample_images-1024x711.png.webp)
**Visdrone19-Detection dataset with annotations**
帶註解的 Visdrone19-Detection 資料集

### 建立 YAML 檔案

在開始訓練之前，還有幾個額外的步驟。因為我要訓練一個 YOLO 模型，我會建立一個包含資料集資訊的 YAML 檔案。

![YAML file for dataset](https://visionbrick.com/wp-content/uploads/2025/11/image-21.png.webp)
**YAML file for dataset**
資料集的 YAML 檔案

### 開始訓練

好，現在我們可以開始用切片資料集訓練了。我會把 `yolo11n.pt` 當作預訓練模型使用，但你也可以自由使用其他模型。

```python
from ultralytics import YOLO

model = YOLO('yolo11n.pt')

results = model.train(
    data="dataset.yaml",
    epochs=50,
    imgsz=640,
    batch=16,
    name='yolo11_visdrone_sliced',
    project='runs/train',
    device='cuda',
    patience=10,
    save=True,
    plots=True,
    verbose=True
)
```

訓練開始了。即使我只用了 VisDrone19-Detection 資料集裡 2000×1500 解析度的影像，一個 epoch 大約花了 8 分鐘。2000×1500 解析度下有 772 張影像，切片後則有 9300 張。訓練 8 小時後結束。

![Model training with sliced images](https://visionbrick.com/wp-content/uploads/2025/11/image-27-1024x291.png.webp)
**Model training with sliced images**
使用切片影像進行模型訓練

### 測試新模型

現在，是時候測試新模型了。同樣地，我會用 `get_sliced_prediction` 函式搭配新訓練的模型。

```python
from sahi import AutoDetectionModel
from sahi.predict import get_sliced_prediction

best_model_path = "runs/train/yolo11_visdrone_sliced/weights/best.pt"
test_image = "../test_image.jpg"

detection_model = AutoDetectionModel.from_pretrained(
    model_type='ultralytics',
    model_path=best_model_path,
    confidence_threshold=0.3,
    device="cuda",
)

result = get_sliced_prediction(
    test_image,
    detection_model,
    slice_height=640,
    slice_width=640,
    overlap_height_ratio=0.2,
    overlap_width_ratio=0.2
)

result.export_visuals(export_dir="runs/predictions/")
```

![Small Object Detection with SAHI](https://visionbrick.com/wp-content/uploads/2025/11/image-30.png.webp)
**Small Object Detection with SAHI**
使用 SAHI 偵測小型物體

---

## 結語

好了，我就到這裡。希望你喜歡，如果有任何問題，歡迎隨時問我（siromermer@gmail.com）

---

## 參考資料

- SAHI Paper: https://arxiv.org/abs/2202.06934
- SAHI GitHub: https://github.com/obss/sahi
- Ultralytics: https://github.com/ultralytics/ultralytics