施勢帆老師的教學網站

 找回密碼
 立即註冊
搜索
熱搜: 活動 交友 discuz
查看: 67|回復: 0

OpenCV 人臉辨識程式

[複製鏈接]

706

主題

717

帖子

3406

積分

管理員

Rank: 9Rank: 9Rank: 9

積分
3406
發表於 2025-4-8 16:42:29 | 顯示全部樓層 |閱讀模式
import cv2
import os
import numpy as np
from PIL import Image

# 創建人臉檢測器和辨識器
face_cascade = cv2.CascadeClassifier(cv2.data.haarcascades + 'haarcascade_frontalface_default.xml')
recognizer = cv2.face.LBPHFaceRecognizer_create()

# 準備訓練數據
def get_images_and_labels(data_folder):
    face_samples = []
    ids = []
    id_names = {}  # 用於映射ID到名字的字典

    # 遍歷數據文件夾中的每個子文件夾(每個人一個文件夾)
    for root, dirs, files in os.walk(data_folder):
        for subdir in dirs:
            subject_path = os.path.join(root, subdir)

            # 獲取當前人物的ID(使用文件夾名稱作為ID)
            current_id = int(subdir)
            id_names[current_id] = subdir  # 存儲ID到名字的映射

            # 遍歷當前人物的所有圖片
            for filename in os.listdir(subject_path):
                if filename.startswith("."):
                    continue  # 跳過隱藏文件

                path = os.path.join(subject_path, filename)

                # 將圖片轉換為灰度圖
                pil_image = Image.open(path).convert('L')
                image_np = np.array(pil_image, 'uint8')

                # 檢測人臉
                faces = face_cascade.detectMultiScale(image_np)

                for (x, y, w, h) in faces:
                    face_samples.append(image_np[y:y+h, x:x+w])
                    ids.append(current_id)

    return face_samples, ids, id_names

# 訓練人臉辨識器
def train_recognizer(data_folder):
    print("正在訓練人臉辨識器...")
    faces, ids, id_names = get_images_and_labels(data_folder)
    recognizer.train(faces, np.array(ids))
    recognizer.save('trainer.yml')
    print("訓練完成!已保存訓練數據到 trainer.yml")
    return id_names

# 人臉辨識函數
def recognize_faces():
    # 加載訓練數據
    if not os.path.exists('trainer.yml'):
        print("錯誤:找不到訓練數據文件 (trainer.yml),請先運行訓練程序。")
        return

    recognizer.read('trainer.yml')

    # 初始化攝像頭
    cap = cv2.VideoCapture(0)

    while True:
        ret, frame = cap.read()
        if not ret:
            break

        gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)

        # 檢測人臉
        faces = face_cascade.detectMultiScale(gray, scaleFactor=1.2, minNeighbors=5)

        for (x, y, w, h) in faces:
            # 繪製人臉矩形框
            cv2.rectangle(frame, (x, y), (x+w, y+h), (0, 255, 0), 2)

            # 進行辨識
            id_, confidence = recognizer.predict(gray[y:y+h, x:x+w])

            # 計算置信度百分比
            confidence_percent = round(100 - confidence)

            # 如果置信度高於50%,則顯示辨識結果
            if confidence_percent > 50:
                name = id_names.get(id_, f"未知 ({id_})")
                text = f"{name} ({confidence_percent}%)"
            else:
                text = "未知"

            cv2.putText(frame, text, (x, y-10), cv2.FONT_HERSHEY_SIMPLEX, 0.9, (0, 255, 0), 2)

        # 顯示結果
        cv2.imshow('人臉辨識', frame)

        # 按'q'退出
        if cv2.waitKey(1) & 0xFF == ord('q'):
            break

    cap.release()
    cv2.destroyAllWindows()

# 主程序
if __name__ == "__main__":
    # 數據文件夾路徑(每個人一個子文件夾,文件夾名稱為ID)
    data_folder = "dataset"

    # 如果數據文件夾不存在,創建它
    if not os.path.exists(data_folder):
        os.makedirs(data_folder)
        print(f"已創建數據文件夾: {data_folder}")
        print("請在該文件夾中為每個人創建子文件夾,文件夾名稱為數字ID,並放入該人的照片。")
    else:
        # 訓練或辨識
        choice = input("輸入 'train' 訓練模型,或 'recognize' 進行辨識: ").lower()

        if choice == 'train':
            id_names = train_recognizer(data_folder)
        elif choice == 'recognize':
            # 加載ID到名字的映射
            id_names = {}
            for root, dirs, files in os.walk(data_folder):
                for subdir in dirs:
                    id_names[int(subdir)] = subdir
            recognize_faces()
        else:
            print("無效的選擇。")


# OpenCV 人臉辨識程式

以下是一個使用OpenCV進行人臉辨識的Python程式,可以辨識不同的人臉。這個程式使用了OpenCV的預訓練人臉檢測模型,並結合LBPH (Local Binary Patterns Histograms) 人臉辨識器來訓練和辨識不同的人。

## 完整程式碼

```python
import cv2
import os
import numpy as np
from PIL import Image

# 創建人臉檢測器和辨識器
face_cascade = cv2.CascadeClassifier(cv2.data.haarcascades + 'haarcascade_frontalface_default.xml')
recognizer = cv2.face.LBPHFaceRecognizer_create()

# 準備訓練數據
def get_images_and_labels(data_folder):
    face_samples = []
    ids = []
    id_names = {}  # 用於映射ID到名字的字典

    # 遍歷數據文件夾中的每個子文件夾(每個人一個文件夾)
    for root, dirs, files in os.walk(data_folder):
        for subdir in dirs:
            subject_path = os.path.join(root, subdir)

            # 獲取當前人物的ID(使用文件夾名稱作為ID)
            current_id = int(subdir)
            id_names[current_id] = subdir  # 存儲ID到名字的映射

            # 遍歷當前人物的所有圖片
            for filename in os.listdir(subject_path):
                if filename.startswith("."):
                    continue  # 跳過隱藏文件

                path = os.path.join(subject_path, filename)

                # 將圖片轉換為灰度圖
                pil_image = Image.open(path).convert('L')
                image_np = np.array(pil_image, 'uint8')

                # 檢測人臉
                faces = face_cascade.detectMultiScale(image_np)

                for (x, y, w, h) in faces:
                    face_samples.append(image_np[y:y+h, x:x+w])
                    ids.append(current_id)

    return face_samples, ids, id_names

# 訓練人臉辨識器
def train_recognizer(data_folder):
    print("正在訓練人臉辨識器...")
    faces, ids, id_names = get_images_and_labels(data_folder)
    recognizer.train(faces, np.array(ids))
    recognizer.save('trainer.yml')
    print("訓練完成!已保存訓練數據到 trainer.yml")
    return id_names

# 人臉辨識函數
def recognize_faces():
    # 加載訓練數據
    if not os.path.exists('trainer.yml'):
        print("錯誤:找不到訓練數據文件 (trainer.yml),請先運行訓練程序。")
        return

    recognizer.read('trainer.yml')

    # 初始化攝像頭
    cap = cv2.VideoCapture(0)

    while True:
        ret, frame = cap.read()
        if not ret:
            break

        gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)

        # 檢測人臉
        faces = face_cascade.detectMultiScale(gray, scaleFactor=1.2, minNeighbors=5)

        for (x, y, w, h) in faces:
            # 繪製人臉矩形框
            cv2.rectangle(frame, (x, y), (x+w, y+h), (0, 255, 0), 2)

            # 進行辨識
            id_, confidence = recognizer.predict(gray[y:y+h, x:x+w])

            # 計算置信度百分比
            confidence_percent = round(100 - confidence)

            # 如果置信度高於50%,則顯示辨識結果
            if confidence_percent > 50:
                name = id_names.get(id_, f"未知 ({id_})")
                text = f"{name} ({confidence_percent}%)"
            else:
                text = "未知"

            cv2.putText(frame, text, (x, y-10), cv2.FONT_HERSHEY_SIMPLEX, 0.9, (0, 255, 0), 2)

        # 顯示結果
        cv2.imshow('人臉辨識', frame)

        # 按'q'退出
        if cv2.waitKey(1) & 0xFF == ord('q'):
            break

    cap.release()
    cv2.destroyAllWindows()

# 主程序
if __name__ == "__main__":
    # 數據文件夾路徑(每個人一個子文件夾,文件夾名稱為ID)
    data_folder = "dataset"

    # 如果數據文件夾不存在,創建它
    if not os.path.exists(data_folder):
        os.makedirs(data_folder)
        print(f"已創建數據文件夾: {data_folder}")
        print("請在該文件夾中為每個人創建子文件夾,文件夾名稱為數字ID,並放入該人的照片。")
    else:
        # 訓練或辨識
        choice = input("輸入 'train' 訓練模型,或 'recognize' 進行辨識: ").lower()

        if choice == 'train':
            id_names = train_recognizer(data_folder)
        elif choice == 'recognize':
            # 加載ID到名字的映射
            id_names = {}
            for root, dirs, files in os.walk(data_folder):
                for subdir in dirs:
                    id_names[int(subdir)] = subdir
            recognize_faces()
        else:
            print("無效的選擇。")
```

## 使用說明

1. **準備數據集**:
   - 創建一個名為 `dataset` 的文件夾
   - 在 `dataset` 中為每個人創建一個子文件夾,文件夾名稱使用數字ID(例如:1, 2, 3...)
   - 在每個人的文件夾中放入該人的多張照片(最好有10-20張,包含不同角度和表情)

2. **訓練模型**:
   - 運行程序並選擇 `train` 選項
   - 程式會讀取 `dataset` 文件夾中的圖片並訓練模型
   - 訓練完成後會生成 `trainer.yml` 文件

3. **進行辨識**:
   - 運行程序並選擇 `recognize` 選項
   - 程式會打開攝像頭並開始實時辨識人臉
   - 按 `q` 鍵退出

## 進階改進

1. **提高準確率**:
   - 增加更多訓練圖片
   - 使用更高質量的圖片
   - 嘗試不同的辨識算法(如EigenFace或FisherFace)

2. **添加新功能**:
   - 添加註冊新用戶的功能
   - 保存辨識記錄
   - 增加人臉特徵點檢測

3. **性能優化**:
   - 使用多線程處理
   - 調整檢測參數(scaleFactor, minNeighbors等)
   - 使用GPU加速

這個程式提供了基本的人臉辨識功能,你可以根據需要進一步擴展和改進它。

本帖子中包含更多資源

您需要 登錄 才可以下載或查看,沒有帳號?立即註冊

x
回復

使用道具 舉報

您需要登錄後才可以回帖 登錄 | 立即註冊

本版積分規則

Archiver|手機版|小黑屋|施勢帆老師的教學網站

GMT+8, 2025-4-19 08:11 , Processed in 0.034493 second(s), 19 queries .

Powered by Discuz! X3.4

Copyright © 2001-2021, Tencent Cloud.

快速回復 返回頂部 返回列表