使用 OpenCV DNN 與 DenseNet-121 模型進行圖片分類

使用 OpenCV DNN 與 DenseNet-121 模型進行圖片分類教學

使用 OpenCV DNN 與 DenseNet-121 模型進行圖片分類教學

在這篇教學中,我將帶你一步步使用 OpenCV 的 DNN 模組,搭配 DenseNet-121 預訓練模型,對圖片進行物件分類。無論你是初學者還是有些基礎,這份教學都能幫助你快速上手。

一、準備工作

1. 安裝環境

請先確定你已安裝以下套件:

pip install opencv-python numpy
注意:建議使用 OpenCV 4.5 以上版本,因為較新版改善了 DNN 模組的穩定性和功能。

2. 下載模型與資料

  • DenseNet_121.caffemodel:模型權重檔
  • DenseNet_121.prototxt:網路結構描述檔
  • classification_classes_ILSVRC2012.txt:分類名稱清單(ImageNet 1000 類)

請將以上檔案放到你的專案資料夾,例如:

ch03/
  ├─ models/
  │    ├─ DenseNet_121.caffemodel
  │    ├─ DenseNet_121.prototxt
  │    └─ classification_classes_ILSVRC2012.txt
  └─ images/
       └─ cat3.jpg
重要提醒:
確認檔案副檔名正確,特別是 prototxt 檔不要誤加 .txt,這會造成讀取失敗。

二、程式碼詳解

以下是完整範例程式碼,我會逐步說明每個部分的功能與用法。

import cv2
import numpy as np

# 模型與分類標籤路徑
model_path = r"ch03/models/DenseNet_121.caffemodel"
config_path = r"ch03/models/DenseNet_121.prototxt"
classifier_path = r"ch03/models/classification_classes_ILSVRC2012.txt"

# 讀取分類名稱
class_names = []
with open(classifier_path, 'r') as f:
    for line in f.readlines():
        # 分割逗號前的類別名稱並去除空白
        class_names.append(line.split(',')[0].strip())

print(f"類別名稱數量:{len(class_names)}")

# 載入模型
model = cv2.dnn.readNet(model=model_path, config=config_path, framework="Caffe")

# 載入測試圖片
img = cv2.imread("ch03/images/cat3.jpg")

# 定義前處理函式與推論
def blobFromImage(img):
    # 將圖片轉成標準輸入格式 blob
    blob = cv2.dnn.blobFromImage(img, scalefactor=0.01, size=(224,224), mean=(104.0, 177.0, 123))
    model.setInput(blob)
    outputs = model.forward()
    # 將輸出結果調成1000x1符合類別數
    final_outputs = outputs[0].reshape(1000, 1)
    return final_outputs

# 執行推論
final_outputs = blobFromImage(img)

# 定義 softmax 轉機率函式
def softmax(x):
    e_x = np.exp(x - np.max(x))  # 減去最大值避免溢位
    return e_x / e_x.sum()

probs = softmax(final_outputs)
final_probs = np.round(np.max(probs)*100, 2)  # 最高機率(%)
label_id = np.argmax(probs)  # 找出最高機率索引
out_name = class_names[label_id]

print(f"預測結果:{out_name},機率:{final_probs}%")

# 在圖片上顯示結果
cv2.putText(img, out_name, (25, 50), cv2.FONT_HERSHEY_SIMPLEX, 1, (0, 255, 0), 2)
cv2.putText(img, f"{final_probs}%", (25, 100), cv2.FONT_HERSHEY_SIMPLEX, 1, (0, 255, 0), 2)

# 顯示圖片
cv2.imshow("Prediction", img)
cv2.waitKey(0)
cv2.destroyAllWindows()

程式碼重點說明

  • 路徑設定model_pathconfig_pathclassifier_path 指向你的模型檔與分類檔案。
  • 分類名稱讀取:將文字檔中每一行的類別名稱載入清單。
  • 模型載入:利用 OpenCV 的 readNet 載入 Caffe 格式模型。
  • 圖片讀取:使用 cv2.imread 載入欲分類圖片。
  • 前處理與推論:將圖片轉成模型輸入 blob,執行前向推論得到輸出。
  • softmax 機率計算:將模型輸出 logits 轉換成機率分佈。
  • 結果顯示:在圖片上標記分類名稱與機率,並以視窗顯示。

三、注意事項

  • 確定路徑與檔案名稱無誤,包括副檔名。
  • 模型輸入尺寸必須與訓練時一致,DenseNet-121 通常是 224x224。
  • 均值參數 (104.0, 177.0, 123) 需與模型訓練時使用的設定相符。
  • 若模型載入失敗,請檢查 OpenCV 版本與檔案完整性。
  • 可以嘗試不同圖片測試,驗證模型效果。

四、結語

現在你已經完成了從讀取模型、處理圖片到輸出分類結果的完整流程。OpenCV DNN 模組讓部署深度學習模型變得簡單快速,不需要安裝 TensorFlow 或 PyTorch 等重量級框架。

如果你喜歡這篇教學,歡迎分享給更多朋友,或在留言區告訴我你的使用心得,也歡迎提出問題讓我協助解決!

祝你專案順利,玩得愉快!

留言

這個網誌中的熱門文章

opencv-畫線條/矩陣/圓/文字

opencv-圖像相素調整(resize)和剪裁(cropping)

原來opencv也能"訓練"人臉辨識