基于Pytorch的人臉識別程序

人臉識別原理詳解

人臉識別是模式識別和計算機視覺領域的重要研究方向,其目標是從圖像或視頻中識別出特定個體的身份。現代人臉識別技術主要基于深度學習方法,特別是卷積神經網絡 (CNN),下面從多個維度詳細解析其原理:

1. 人臉識別的基本流程

人臉識別系統通常包含以下核心模塊:

  • 人臉檢測:從圖像中定位并提取人臉區域
  • 人臉對齊:基于面部特征點 (如眼睛、鼻子、嘴巴) 對人臉進行歸一化
  • 特征提取:將對齊后的人臉圖像映射為固定維度的特征向量
  • 特征匹配:通過計算特征向量間的相似度進行身份驗證或識別
2. 人臉識別的核心技術
2.1 基于深度學習的特征提取

現代人臉識別技術的突破主要歸功于深度卷積神經網絡的應用。典型的人臉識別網絡結構包括:

  • 骨干網絡 (Backbone):通常采用 ResNet、MobileNet 等架構提取圖像特征
  • 特征增強層:如 SE 模塊 (Squeeze-and-Excitation)、注意力機制等
  • 損失函數設計
    • Softmax 損失:直接分類
    • Triplet 損失:學習類內緊湊、類間分離的特征空間
    • ArcFace/Additive Angular Margin Loss:通過角度間隔優化特征分布
2.2 特征匹配與識別

提取的特征向量通常被歸一化為單位長度,然后通過計算余弦相似度進行匹配:相似度=cos(\theta )=\frac{\mathbf{A}\cdot\mathbf{B}}}}{\left \| \mathbf{A} \right \|\cdot\left \| \mathbf{B} \right \|}

當相似度超過設定閾值時,判定為同一人。?

3. 人臉識別中的挑戰
  • 姿態變化:正面、側面、仰頭、低頭等不同姿態
  • 光照變化:強光、弱光、逆光等環境差異
  • 表情變化:微笑、憤怒、驚訝等面部表情
  • 年齡變化:隨著年齡增長面部特征的變化
  • 遮擋問題:眼鏡、口罩、胡須等遮擋物
4. 人臉識別的評價指標
  • 準確率 (Accuracy):正確分類樣本數占總樣本數的比例
  • ROC 曲線:真陽性率 (TPR) 與假陽性率 (FPR) 的關系曲線
  • EER(Equal Error Rate):錯誤接受率 (FAR) 等于錯誤拒絕率 (FRR) 時的值
  • ROC 曲線下面積 (AUC):衡量分類器性能的綜合指標

基于 PyTorch 的人臉識別程序實現

下面是完整的 PyTorch 實現代碼:

?

import os
import numpy as np
import torch
import torch.nn as nn
import torch.optim as optim
from torch.utils.data import Dataset, DataLoader
from torchvision import transforms
from PIL import Image
import matplotlib.pyplot as plt# 設置隨機種子確保結果可復現
torch.manual_seed(42)
np.random.seed(42)class FaceDataset(Dataset):"""自定義人臉數據集類"""def __init__(self, root_dir, transform=None):"""初始化人臉數據集參數:root_dir: 數據集根目錄transform: 圖像預處理轉換"""self.root_dir = root_dirself.transform = transformself.images = []  # 存儲圖像路徑self.labels = []  # 存儲標簽# 遍歷每個子文件夾(每個人)for person_id, person_name in enumerate(sorted(os.listdir(root_dir))):person_dir = os.path.join(root_dir, person_name)if os.path.isdir(person_dir):# 遍歷該人所有圖像for img_name in os.listdir(person_dir):if img_name.endswith('.pgm'):img_path = os.path.join(person_dir, img_name)self.images.append(img_path)self.labels.append(person_id)def __len__(self):"""返回數據集大小"""return len(self.images)def __getitem__(self, idx):"""獲取指定索引的圖像和標簽"""img_path = self.images[idx]label = self.labels[idx]# 讀取圖像image = Image.open(img_path).convert('L')  # 轉為灰度圖# 應用預處理轉換if self.transform:image = self.transform(image)return image, labelclass FaceNet(nn.Module):"""人臉識別網絡模型"""def __init__(self, num_classes=40):"""初始化人臉識別網絡參數:num_classes: 類別數量(人數)"""super(FaceNet, self).__init__()# 定義卷積神經網絡結構self.features = nn.Sequential(# 第一層卷積nn.Conv2d(1, 32, kernel_size=3, stride=1, padding=1),nn.BatchNorm2d(32),nn.ReLU(inplace=True),nn.MaxPool2d(kernel_size=2, stride=2),# 第二層卷積nn.Conv2d(32, 64, kernel_size=3, stride=1, padding=1),nn.BatchNorm2d(64),nn.ReLU(inplace=True),nn.MaxPool2d(kernel_size=2, stride=2),# 第三層卷積nn.Conv2d(64, 128, kernel_size=3, stride=1, padding=1),nn.BatchNorm2d(128),nn.ReLU(inplace=True),nn.MaxPool2d(kernel_size=2, stride=2),# 第四層卷積nn.Conv2d(128, 256, kernel_size=3, stride=1, padding=1),nn.BatchNorm2d(256),nn.ReLU(inplace=True),nn.MaxPool2d(kernel_size=2, stride=2),)# 創建一個虛擬輸入來計算特征維度self.feature_size = self._get_feature_size()# 全連接層用于特征提取self.fc = nn.Sequential(nn.Linear(self.feature_size, 512),nn.BatchNorm1d(512),nn.ReLU(inplace=True),nn.Dropout(0.5),nn.Linear(512, 128),  # 提取128維特征向量nn.BatchNorm1d(128),)# 分類層self.classifier = nn.Linear(128, num_classes)def _get_feature_size(self):"""計算特征向量維度"""# 創建一個虛擬輸入(1通道,112x92尺寸)x = torch.zeros(1, 1, 112, 92)x = self.features(x)# 展平后的尺寸return x.view(1, -1).size(1)def forward(self, x):"""前向傳播過程"""x = self.features(x)x = x.view(x.size(0), -1)  # 展平features = self.fc(x)      # 提取特征向量logits = self.classifier(features)  # 分類return features, logitsdef train_model(model, train_loader, criterion, optimizer, device, epochs=20):"""訓練人臉識別模型參數:model: 模型train_loader: 訓練數據加載器criterion: 損失函數optimizer: 優化器device: 計算設備epochs: 訓練輪數"""model.train()train_losses = []for epoch in range(epochs):running_loss = 0.0correct = 0total = 0for inputs, labels in train_loader:inputs, labels = inputs.to(device), labels.to(device)# 梯度清零optimizer.zero_grad()# 前向傳播_, outputs = model(inputs)loss = criterion(outputs, labels)# 反向傳播和優化loss.backward()optimizer.step()# 統計running_loss += loss.item()_, predicted = outputs.max(1)total += labels.size(0)correct += predicted.eq(labels).sum().item()# 計算平均損失和準確率epoch_loss = running_loss / len(train_loader)epoch_acc = 100.0 * correct / totaltrain_losses.append(epoch_loss)print(f'Epoch {epoch+1}/{epochs}, Loss: {epoch_loss:.4f}, Acc: {epoch_acc:.2f}%')return train_lossesdef evaluate_model(model, test_loader, device):"""評估人臉識別模型參數:model: 模型test_loader: 測試數據加載器device: 計算設備"""model.eval()correct = 0total = 0all_features = []all_labels = []with torch.no_grad():for inputs, labels in test_loader:inputs, labels = inputs.to(device), labels.to(device)# 提取特征和預測features, outputs = model(inputs)_, predicted = outputs.max(1)# 統計total += labels.size(0)correct += predicted.eq(labels).sum().item()# 保存特征和標簽用于后續分析all_features.append(features.cpu().numpy())all_labels.append(labels.cpu().numpy())# 計算準確率accuracy = 100.0 * correct / totalprint(f'測試集準確率: {accuracy:.2f}%')# 轉換為numpy數組all_features = np.vstack(all_features)all_labels = np.hstack(all_labels)return accuracy, all_features, all_labelsdef main():"""主函數"""# 設置計算設備device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')print(f'使用設備: {device}')# 定義數據預處理train_transform = transforms.Compose([transforms.Resize((112, 92)),  # 調整圖像大小transforms.RandomHorizontalFlip(),  # 隨機水平翻轉transforms.ToTensor(),  # 轉為Tensor并歸一化到[0,1]transforms.Normalize(mean=[0.5], std=[0.5])  # 標準化])test_transform = transforms.Compose([transforms.Resize((112, 92)),transforms.ToTensor(),transforms.Normalize(mean=[0.5], std=[0.5])])# 創建數據集train_dataset = FaceDataset(root_dir=r'D:\數據集\faces\training',transform=train_transform)test_dataset = FaceDataset(root_dir=r'D:\數據集\faces\testing',transform=test_transform)# 創建數據加載器train_loader = DataLoader(train_dataset,batch_size=32,shuffle=True,num_workers=4)test_loader = DataLoader(test_dataset,batch_size=32,shuffle=False,num_workers=4)# 初始化模型model = FaceNet(num_classes=40).to(device)# 打印模型信息print("模型結構:")print(model)print(f"特征向量維度: {model.feature_size}")# 定義損失函數和優化器criterion = nn.CrossEntropyLoss()optimizer = optim.Adam(model.parameters(), lr=0.001)# 訓練模型print("開始訓練模型...")train_losses = train_model(model, train_loader, criterion, optimizer, device)# 評估模型print("開始評估模型...")accuracy, features, labels = evaluate_model(model, test_loader, device)# 保存模型torch.save(model.state_dict(), 'face_recognition_model.pth')print("模型已保存為: face_recognition_model.pth")# 繪制訓練損失曲線plt.figure(figsize=(10, 6))plt.plot(train_losses)plt.title('Training Loss')plt.xlabel('Epoch')plt.ylabel('Loss')plt.grid(True)plt.savefig('training_loss.png')plt.show()if __name__ == "__main__":main()    

代碼解析

上述代碼實現了一個完整的人臉識別系統,主要包含以下幾個部分:

  1. 數據集處理

    • 創建了FaceDataset類來加載 PGM 格式的人臉圖像
    • 自動從文件夾結構中提取類別標簽
    • 支持圖像預處理和增強
  2. 模型架構

    • 使用四層卷積網絡提取人臉特征
    • 最后兩層全連接層分別用于特征提取和分類
    • 提取 128 維的特征向量用于人臉識別
  3. 訓練過程

    • 使用交叉熵損失函數進行分類訓練
    • 采用 Adam 優化器,學習率設為 0.001
    • 訓練 20 個輪次并記錄訓練損失
  4. 評估過程

    • 在測試集上評估模型準確率
    • 保存提取的特征向量用于后續分析

這個實現采用了經典的分類方法進行人臉識別,通過訓練一個多類分類器,使得同一個人的特征向量在特征空間中接近,不同人的特征向量遠離。在實際應用中,還可以進一步改進,例如使用 Triplet Loss 或 ArcFace 等更先進的損失函數來優化特征空間。

如果需要使用這個程序,只需確保數據集路徑正確,然后運行代碼即可。訓練完成后,模型會保存為face_recognition_model.pth,同時生成訓練損失曲線圖表。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/pingmian/89700.shtml
繁體地址,請注明出處:http://hk.pswp.cn/pingmian/89700.shtml
英文地址,請注明出處:http://en.pswp.cn/pingmian/89700.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

ubuntu 開啟ssh踩坑之旅

文章目錄確認當前用戶為普通用戶 or root命令使用ssh還是sshd服務名稱的由來apt update和apt upgrade的關系apt upgrade報錯:“E: 您在 /var/cache/apt/archives/ 上沒有足夠的可用空間”開啟ssh步驟錯誤排查查看日志修改sshd_config文件允許防火墻通過22端口確認當…

力扣:動態規劃java

sub07 線性DP - O(1) 狀態轉移2_嗶哩嗶哩_bilibili 跳樓梯 class Solution {public int climbStairs(int n) {if (n < 1) {return 1; // 處理邊界情況}int[] dp new int[n 1]; // 創建長度為n1的數組&#xff0c;比方說跳二級樓梯dp[0] 1; // 初始值設定dp[1] 1;for (…

React Native打開相冊選擇圖片或拍照 -- react-native-image-picker

官方文檔&#xff1a;https://www.npmjs.com/package/react-native-image-picker 場景&#xff1a;點擊按鈕打開相冊選擇圖片或者點擊按鈕拍照 import { launchCamera, launchImageLibrary } from react-native-image-picker;// ... <TouchableOpacityactiveOpacity{0.7}o…

USRP B210生成信號最大帶寬測試之Frank

書接上文&#xff1a; USRP B210生成LFM,SFM,BPSK,Frank信號的最大帶寬測試&#xff08;一&#xff09; USRP B210生成信號最大帶寬測試&#xff08;二&#xff09;SFM USRP B210生成信號最大帶寬測試&#xff08;三&#xff09;LFM USRP B210生成信號最大帶寬測試之BPSK …

pages.json頁面路由中,globalStyle的各個屬性

歡迎來到我的UniApp技術專欄&#xff01;&#x1f389; 在這里&#xff0c;我將與大家分享關于UniApp開發的實用技巧、最佳實踐和項目經驗。 專欄特色&#xff1a; &#x1f4f1; 跨平臺開發一站式解決方案 &#x1f680; 從入門到精通的完整學習路徑 &#x1f4a1; 實戰項目經…

[前端技術基礎]CSS選擇器沖突解決方法-由DeepSeek產生

在 CSS 中&#xff0c;當多個選擇器對同一元素的相同屬性&#xff08;如顏色&#xff09;定義發生沖突時&#xff0c;瀏覽器會通過層疊規則&#xff08;Cascading&#xff09;解決沖突。具體優先級從高到低如下&#xff1a;1. !important 規則&#xff08;最高優先級&#xff0…

解決 IDEA 中 XML 文件的 “URI is not registered” 報錯

解決 IDEA 中 XML 文件的 “URI is not registered” 報錯 在使用 IDEA 開發時&#xff0c;XML 文件&#xff08;尤其是帶有 DTD 約束的配置文件&#xff0c;如 MyBatis、Spring 配置文件&#xff09;常出現 URI is not registered (Settings | Languages & Frameworks | S…

FreeBSD Conda Python3.12下安裝GPT4Free(g4f)0.5.7.3版本

FreeBSD下不能直接安裝g4f&#xff0c;因為Curl_cffi這個庫裝不上。0.5.0.3這個版本不需要這個庫&#xff0c;所以可以安裝。 那么就沒有辦法安裝新版本了嗎&#xff1f; 有的&#xff0c;就是在linux仿真環境下。 Linux仿真環境安裝g4f 最簡單的方法是使用chroot進入linux仿…

Node.js 中基于請求 ID 實現簡單隊列(即時阻止策略/排隊等待策略)

在Node.js 中基于請求 ID 實現簡單隊列 下面示例演示兩種策略&#xff0c;以同一個請求 ID 為單位&#xff1a; 即時阻止策略&#xff1a;如果已有相同 ID 的請求在處理&#xff0c;直接報錯并返回。 排隊等待策略&#xff1a;后續相同 ID 的請求不報錯&#xff0c;而是掛起&…

詳解如何解決Mysql主從復制延遲

解決 MySQL 主從復制延遲需要從架構設計、參數調優、硬件優化等多維度綜合處理。一、根本原因分析主從延遲的本質是&#xff1a;從庫的 SQL 線程重放速度 < 主庫的寫入速度 常見瓶頸點&#xff1a;單線程回放&#xff08;MySQL 5.6 前&#xff09;從庫硬件配置低&…

Spring之事務使用指南

Spring之事務使用指南一、事務的基礎概念1.1 什么是事務&#xff1f;1.2 事務的ACID特性1.3 Spring事務的核心優勢二、Spring事務的核心配置三、事務傳播行為&#xff08;Propagation&#xff09;3.1 常用傳播行為詳解3.1.1 REQUIRED&#xff08;默認值&#xff09;3.1.2 SUPPO…

基于FPGA的多級流水線加法器verilog實現,包含testbench測試文件

目錄 1.課題概述 2.系統仿真結果 3.核心程序 4.系統原理簡介 5.參考文獻 6.完整工程文件 1.課題概述 流水線&#xff08;Pipeline&#xff09;技術源于工業生產中的裝配線理念&#xff0c;在數字電路中&#xff0c;它將一個復雜運算任務分解為若干個子任務&#xff0c;每…

5.1.4習題精講

一、單項選擇題 01. 下列部件不屬于控制器的是&#xff08; C &#xff09;。 題目原文 下列部件不屬于控制器的是&#xff08; &#xff09;。 A. 指令寄存器 B. 程序計數器 C. 程序狀態字寄存器 D. 時序電路 正確答案&#xff1a;C 題目解析 考點分析&#xff1a; 本題考察CP…

華為云Flexus+DeepSeek征文|低代碼 × 強推理:華為云 Flexus 搭建可部署的 AI Agent 實踐方案【搭建寵物養護小知識AI助手】

文章目錄華為云FlexusDeepSeek征文&#xff5c;低代碼 強推理&#xff1a;華為云 Flexus 搭建可部署的 AI Agent 實踐方案【搭建寵物養護小知識AI助手】&#x1f680; 引言一、核心技術概覽1. 華為云 Flexus X2. DeepSeek-R1 模型3. Dify 平臺二、總體架構設計三、環境準備與資…

基于智慧經營系統的學校住宿登記報表分析與應用探究-畢業論文—仙盟創夢IDE

摘要本文聚焦學校住宿場景&#xff0c;以 “未來之窗智慧經營&#xff08;學校住宿&#xff09;” 系統生成的日報表、昨日報表、本月報表為研究對象&#xff0c;深入剖析報表數據結構、功能價值及在住宿管理中的應用。通過解讀水費、電費、押金、房費、總計、訂單等數據維度&a…

arping(ARP協議網絡測試工具)

1. 項目介紹&#xff1a;arping 是一個用于在局域網&#xff08;LAN&#xff09;中查找特定 IP 地址是否被占用的實用工具。與傳統的 ping 命令不同&#xff0c;arping 使用 ARP 協議來發送和接收數據包&#xff0c;從而能夠檢測到那些阻止 ICMP 請求的主機。arping 可以幫助網…

【UE5醫學影像可視化】讀取dicom數據生成2D紋理并顯示

文章目錄1.實現目標2.實現過程2.1 數據準備2.2 創建項目2.3 dcmtk庫集成2.4 流程&原理2.5 材質2.6 應用實現3.參考資料1.實現目標 本文在UE5中讀取本地的dicom文件&#xff0c;解析像素值、窗寬窗位等信息&#xff0c;生成2D紋理&#xff0c;在UE場景中實現簡單的2D醫學影像…

lua(xlua)基礎知識點記錄一

1. 關于 (…) 操作符 編譯階段優化&#xff1a;Lua 編譯器會對常量字符串進行優化處理&#xff0c;將連續的字符串拼接操作 (…) 合并為單個字符串。這種優化僅適用于編譯期確定的常量字符串&#xff0c;不適用于運行時生成的動態字符串。 示例&#xff1a;local str "He…

【Python數據采集】Python爬取小紅書搜索關鍵詞下面的所有筆記的內容、點贊數量、評論數量等數據,繪制詞云圖、詞頻分析、數據分析

Python爬取小紅書搜索關鍵詞下面的所有筆記的內容、點贊數量、評論數量等數據&#xff0c;繪制詞云圖、詞頻分析、數據分析 使用 Python 編寫一個簡單的爬蟲程序來從小紅書抓取與指定關鍵詞相關的筆記數據&#xff0c;并對這些數據進行基本的數據分析&#xff0c;包括詞云圖和…

最大子數組和問題-詳解Kadane算法

最大子數組和問題-詳解Kadane算法一、問題定義與暴力解法1.1 問題描述1.2 暴力解法的低效性二、Kadane算法的核心原理2.1 動態規劃思想的應用2.2 優化空間復雜度三、Kadane算法的Java實現3.1 基礎版本&#xff08;處理所有情況&#xff09;3.2 算法正確性驗證四、Kadane算法的變…