BANblongz commited on
Commit
90e8331
1 Parent(s): 4c1f24c

Update README.md

Browse files

import cv2
import os
import numpy as np
import random
import joblib
from sklearn import svm
from sklearn.preprocessing import StandardScaler
from sklearn.decomposition import PCA


class FaceRecognizer:
def __init__(self, imgdir='./test_img/', grayfacedir='./test_img_gray', model_path='./svm_model.pkl'):
self.imgdir = imgdir
self.grayfacedir = grayfacedir
self.model_path = model_path
self.svm_model = svm.SVC(kernel='linear', probability=True)
self.face_cascade = cv2.CascadeClassifier(cv2.data.haarcascades + 'haarcascade_frontalface_default.xml')
self.label_map = {}
self.pca_model = None # 初始化 pca_model 为 None


def collect_data(self, someone, picturenum=50):
"""
收集人脸数据并保存图像,同时进行数据增强
"""
person_dir = self._create_person_directory(someone)
capture = cv2.VideoCapture(0)

cv2.waitKey(1)

count = 0
while count < picturenum:
ret, img = capture.read()
if not ret:
print("无法获取图像")
break

gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
faces = self.detect_faces(gray)

for (x, y, w, h) in faces:
face_img = gray[y:y + h, x:x + w]
augmented_faces = self.augment_face(face_img)

for augmented_face in augmented_faces:
picturepath = os.path.join(person_dir, f'{count + 1}.jpg')
cv2.imwrite(picturepath, augmented_face)
count += 1

if count >= picturenum:
break

cv2.imshow(f'Capturing Face - {someone}', img)

if cv2.waitKey(100) == ord('q'):
break

capture.release()
cv2.destroyAllWindows()

def _create_person_directory(self, someone):
"""
创建人物名称的子文件夹
"""
person_dir = os.path.join(self.imgdir, someone)
if not os.path.exists(person_dir):
os.makedirs(person_dir)
return person_dir

def detect_faces(self, gray):
"""
检测图像中的人脸
"""
faces = self.face_cascade.detectMultiScale(gray, scaleFactor=1.1, minNeighbors=5, minSize=(30, 30))
return faces

def augment_face(self, face_img):
"""
对人脸图像进行数据增强,包括旋转、镜像、平移等
"""
augmented_faces = [cv2.flip(face_img, 1)] # 镜像(水平翻转)

angle = random.uniform(-10, 10) # 随机旋转
augmented_faces.append(self.rotate_image(face_img, angle))

translation = random.randint(-5, 5) # 随机平移
augmented_faces.append(self.translate_image(face_img, translation))

return augmented_faces

def rotate_image(self, image, angle):
"""
旋转图像指定角度
"""
height, width = image.shape
center = (width // 2, height // 2)
rotation_matrix = cv2.getRotationMatrix2D(center, angle, 1.0)
return cv2.warpAffine(image, rotation_matrix, (width, height))

def translate_image(self, image, tx):
"""
图像平移
"""
height, width = image.shape
translation_matrix = np.float32([[1, 0, tx], [0, 1, 0]])
return cv2.warpAffine(image, translation_matrix, (width, height))

def prepare_data(self):
"""
准备训练数据并进行标准化处理
"""
faces = []
labels = []

person_id = 0
for person_name in os.listdir(self.imgdir):
person_dir = os.path.join(self.imgdir, person_name)
if not os.path.isdir(person_dir):
continue

if person_name not in self.label_map:
self.label_map[person_id] = person_name # 新人物,分配新的ID
person_id += 1

for img_name in os.listdir(person_dir):
img_path = os.path.join(person_dir, img_name)
if img_name.lower().endswith(('.png', '.jpg', '.jpeg')):
img = cv2.imread(img_path)
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)

faces_detected = self.detect_faces(gray)
for (x, y, w, h) in faces_detected:
face = gray[y:y + h, x:x + w]
face_resized = cv2.resize(face, (100, 100))
faces.append(face_resized)
labels.append(self.get_person_id(person_name))

faces = np.array(faces)
faces = faces.reshape(faces.shape[0], -1) # 展平图像数据
faces = StandardScaler().fit_transform(faces) # 进行标准化处理

return faces, labels

def train_svm(self, n_components=50):
"""
使用 PCA 进行降维后,使用 SVM 训练模型
"""
faces, labels = self.prepare_data()
self.pca = PCA(n_components=n_components, whiten=True)
faces_pca = self.pca.fit_transform(faces)

self.svm_model.fit(faces_pca, labels)

self.save_model()
joblib.dump(self.pca, './pca_model.pkl')
print("SVM 模型和 PCA 降维模型训练完成!")

def get_person_id(self, person_name):
"""
根据人物名称获取对应的ID,如果没有,则让用户命名
"""
if person_name not in self.label_map.values():
new_name = input(f"请输入 {person_name} 的名称:")
person_id = len(self.label_map)
self.label_map[person_id] = new_name
print(f"已将 {person_name} 命名为 {new_name}")
return person_id
return list(self.label_map.values()).index(person_name)

def save_model(self):
"""
保存训练好的SVM模型
"""
joblib.dump(self.svm_model, self.model_path)
print(f"模型已保存至 {self.model_path}")

def load_model(self):
"""
加载已保存的SVM模型和PCA模型
"""
self.svm_model = joblib.load(self.model_path)
self.pca_model = joblib.load('./pca_model.pkl') # 加载PCA模型
print(f"模型已加载:{self.model_path} 和 ./pca_model.pkl")

def predict(self, img):
"""
使用训练好的SVM模型进行人脸识别,并应用PCA降维
"""
if self.pca_model is None: # 检查 pca_model 是否已加载
print("PCA模型尚未加载,请先加载模型。")
return

gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
faces_detected = self.face_cascade.detectMultiScale(gray, scaleFactor=1.1, minNeighbors=5, minSize=(30, 30))
for (x, y, w, h) in faces_detected:
face = gray[y:y + h, x:x + w]
face_resized = cv2.resize(face, (100, 100)) # 调整大小
face_flattened = face_resized.flatten().reshape(1, -1)
face_flattened = StandardScaler().fit_transform(face_flattened)
face_pca = self.pca_model.transform(face_flattened) # 使用训练时的PCA进行降维
label = self.svm_model.predict(face_pca)
confidence = self.svm_model.decision_function(face_pca)
person_name = self.label_map.get(label[0], 'Unknown')
print(f"预测标签:{person_name}, 置信度:{confidence}")
cv2.rectangle(img, (x, y), (x + w, y + h), (255, 0, 0), 2)
cv2.putText(img, person_name, (x, y - 10), cv2.FONT_HERSHEY_SIMPLEX, 0.9, (0, 255, 0), 2)


def prepare_data(self):
"""
准备训练数据并进行标准化处理
"""
faces = []
labels = []

person_id = 0
for person_name in os.listdir(self.imgdir):
person_dir = os.path.join(self.imgdir, person_name)
if not os.path.isdir(person_dir):
continue

if person_name not in self.label_map:
self.label_map[person_id] = person_name # 新人物,分配新的ID
person_id += 1

# 处理每个人物的图像
for img_name in os.listdir(person_dir):
img_path = os.path.join(person_dir, img_name)
if img_name.lower().endswith(('.png', '.jpg', '.jpeg')):
img = cv2.imread(img_path)
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)

# 进行人脸检测
faces_detected = self.face_cascade.detectMultiScale(gray, scaleFactor=1.1, minNeighbors=5,
minSize=(30, 30))
for (x, y, w, h) in faces_detected:
face = gray[y:y + h, x:x + w]
face_resized = cv2.resize(face, (100, 100)) # 统一调整大小
faces.append(face_resized)
labels.append(self.get_person_id(person_name))

# 标准化
faces = np.array(faces)
faces = faces.reshape(faces.shape[0], -1) # 展平图像数据
faces = StandardScaler().fit_transform(faces) # 进行标准化处理

return faces, labels
def train_svm(self, n_components=50):
"""
使用 PCA 进行降维后,使用 SVM 训练模型
"""
faces, labels = self.prepare_data()

# 使用 PCA 进行降维
self.pca = PCA(n_components=n_components, whiten=True)
faces_pca = self.pca.fit_transform(faces)

# 使用 SVM 进行训练
self.svm_model.fit(faces_pca, labels)

# 保存模型和 PCA 对象
self.save_model()
joblib.dump(self.pca, './pca_model.pkl')
print("SVM 模型和 PCA 降维模型训练完成!")

def get_person_id(self, person_name):
"""
根据人物名称获取对应的ID,如果没有,则让用户命名
"""
# 如果人物名称不存在,提示用户输入新的名称

Files changed (1) hide show
  1. README.md +8 -1
README.md CHANGED
@@ -1,3 +1,10 @@
 
 
 
 
 
 
 
1
  <!-- markdownlint-disable first-line-h1 -->
2
  <!-- markdownlint-disable html -->
3
  <!-- markdownlint-disable no-duplicate-header -->
@@ -333,4 +340,4 @@ This code repository is licensed under [the MIT License](LICENSE-CODE). The use
333
  ```
334
 
335
  ## 9. Contact
336
- If you have any questions, please raise an issue or contact us at [[email protected]]([email protected]).
 
1
+ ---
2
+ license: apache-2.0
3
+ datasets:
4
+ - HuggingFaceFW/fineweb-2
5
+ language:
6
+ - aa
7
+ ---
8
  <!-- markdownlint-disable first-line-h1 -->
9
  <!-- markdownlint-disable html -->
10
  <!-- markdownlint-disable no-duplicate-header -->
 
340
  ```
341
 
342
  ## 9. Contact
343
+ If you have any questions, please raise an issue or contact us at [[email protected]]([email protected]).