iT邦幫忙

2025 iThome 鐵人賽

DAY 8
0
AI & Data

感知你的動作與情緒:深度學習在人機互動的應用系列 第 8

Day 8 | 手勢識別 (2):用 CNN 打造你的第一個手勢辨識模型

  • 分享至 

  • xImage
  •  

前言

今天將帶你進一步實作一個手勢辨識的 CNN 模型,從資料前處理、模型架構設計,到訓練與評估,一步步帶你打造屬於自己的手勢辨識模型,為未來即時應用打下基礎。


資料集來源

使用的是 Kaggle 上公開的 Sign Language MNIST 資料集,其特點如下:

  • 包含 A~Y(不含 J和Z)共 24 個英文字母手勢類別
  • 每張圖片為 28x28 像素的灰階圖像
  • 訓練資料共 27,455 筆,測試資料共 7,172 筆

這個資料集適合用來進行基礎的圖像分類訓練,能有效協助我們開發初版的手勢辨識模型。


資料前處理

使用 torchvision 與自定義 Dataset 類別來處理圖像資料:

import pandas as pd
import torch
from torch.utils.data import Dataset, DataLoader
from torchvision import transforms
import numpy as np

train_df = pd.read_csv("sign_mnist_train.csv")
test_df = pd.read_csv("sign_mnist_test.csv")

class SignLanguageDataset(Dataset):
    def __init__(self, dataframe, transform=None):
        self.labels = dataframe['label'].values
        self.images = dataframe.drop('label', axis=1).values.reshape(-1, 28, 28).astype(np.uint8)
        self.transform = transform

    def __len__(self):
        return len(self.labels)

    def __getitem__(self, idx):
        image = self.images[idx]
        label = self.labels[idx]
        if self.transform:
            image = self.transform(image)
        return image, label

加入簡單的資料增強策略:

transform = transforms.Compose([
    transforms.ToPILImage(),
    transforms.RandomRotation(10),
    transforms.ToTensor()
])

train_dataset = SignLanguageDataset(train_df, transform=transform)
test_dataset = SignLanguageDataset(test_df, transform=transforms.ToTensor())

用 DataLoader 建立批次資料:

train_loader = DataLoader(train_dataset, batch_size=64, shuffle=True)
test_loader = DataLoader(test_dataset, batch_size=64, shuffle=False)

模型架構:輕量化 CNN 設計

設計了一個 2 層卷積 + 1 層全連接的基本 CNN 架構:

import torch.nn as nn

class GestureCNN(nn.Module):
    def __init__(self):
        super().__init__()
        self.net = nn.Sequential(
            nn.Conv2d(1, 32, kernel_size=3, padding=1),
            nn.ReLU(),
            nn.MaxPool2d(2),

            nn.Conv2d(32, 64, kernel_size=3, padding=1),
            nn.ReLU(),
            nn.MaxPool2d(2),

            nn.Flatten(),
            nn.Linear(64 * 7 * 7, 256),
            nn.ReLU(),
            nn.Linear(256, 25) 
        )

    def forward(self, x):
        return self.net(x)

模型訓練與測試

使用 CrossEntropyLoss 作為分類任務的損失函數,並以 Adam 優化器進行參數更新:

device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
model = GestureCNN().to(device)

loss_fn = nn.CrossEntropyLoss()
optimizer = torch.optim.Adam(model.parameters(), lr=1e-3)

執行訓練迴圈 10 個 epoch:

for epoch in range(10):
    model.train()
    total_loss = 0
    for X, y in train_loader:
        X, y = X.to(device), y.to(device)
        pred = model(X)
        loss = loss_fn(pred, y)

        optimizer.zero_grad()
        loss.backward()
        optimizer.step()
        total_loss += loss.item()

    print(f"Epoch {epoch+1}, Loss: {total_loss:.4f}")

完成訓練後,進行測試集準確率評估:

model.eval()
correct = 0
total = 0

with torch.no_grad():
    for X, y in test_loader:
        X, y = X.to(device), y.to(device)
        pred = model(X)
        predicted = pred.argmax(1)
        correct += (predicted == y).sum().item()
        total += y.size(0)

print(f"Test Accuracy: {correct / total:.4f}")

https://ithelp.ithome.com.tw/upload/images/20250910/20178436XjD72qHTJK.png

結語

藉由今天的內容,帶領你一步步實作出一個簡潔而實用的 靜態手勢辨識 CNN 模型,此篇涵蓋了:

✅ Kaggle 資料集載入與前處理
✅ PyTorch 自定義 Dataset 與 DataLoader
✅ 卷積神經網路(CNN)模型構建
✅ 模型訓練流程與準確率評估

從公開資料中提取影像特徵,成功建立了能分類 24 種英文字母手勢的初步模型,這個過程正是「讓電腦讀懂手勢語意」的第一步。

📌 下一篇文章預告:
把模型從「圖像」推進到「鏡頭」——整合 OpenCV 與 MediaPipe,實現即時的手勢辨識互動,讓你的模型真正看見並理解你!


上一篇
Day 7 | 手勢識別(1):資料集與預處理-MediaPipe + OpenCV 入門
系列文
感知你的動作與情緒:深度學習在人機互動的應用8
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言