经验首页 前端设计 程序设计 Java相关 移动开发 数据库/运维 软件/图像 大数据/云计算 其他经验
当前位置:技术经验 » 程序设计 » Python » 查看文章
[Python急救站]人脸识别技术练习
来源:cnblogs  作者:Jinylin  时间:2024/4/29 9:31:16  对本文有异议

这段时间做了一个用于初学者学习人脸识别系统的程序,在上代码时,先给说说事前准备:

首先我们需要一个OpenCV的一个haarcascade_frontalface_default.xml文件,只要去GitHub上面即可下载:https://github.com/opencv/opencv

点击Code,选择Download ZIP,下载后解压在目录下opencv-4.x\data\haarcascades中可以找到haarcascade_frontalface_default.xml,这个时候将这个文件复制到你的工程目录下。

第二个要准备的文件是:lfw-deepfunneled,这个文件在网站中下载:https://vis-www.cs.umass.edu/lfw/#download

进入网站后下拉找到Download the database:  ,然后在这个模块中找到All images aligned with deep funneling,点击下载后,将压缩包解压到工程目录下即可。

然后创建一个模型训练的py文件,代码如下:

  1. import os
  2. import numpy as np
  3. import cv2
  4. from matplotlib import pyplot as plt
  5. from sklearn.decomposition import PCA
  6. from sklearn.linear_model import LogisticRegression
  7. from sklearn.model_selection import train_test_split
  8. from sklearn.preprocessing import StandardScaler
  9. from sklearn.metrics import classification_report, confusion_matrix
  10. from joblib import dump
  11. # 设置数据集路径
  12. lfw_home = 'D:/Pythonxiangmu/Python/renlian/lfw-deepfunneled' # 替换为实际路径
  13. face_cascade = cv2.CascadeClassifier(cv2.data.haarcascades + 'haarcascade_frontalface_default.xml')
  14. # 函数:从目录加载图像并提取人脸区域
  15. def load_images_and_labels(directory):
  16. images = []
  17. labels = []
  18. for label in sorted(os.listdir(directory)):
  19. if not os.path.isdir(os.path.join(directory, label)):
  20. continue
  21. for img_path in os.listdir(os.path.join(directory, label)):
  22. img = cv2.imread(os.path.join(directory, label, img_path), cv2.IMREAD_GRAYSCALE)
  23. faces = face_cascade.detectMultiScale(img, scaleFactor=1.1, minNeighbors=5)
  24. if len(faces) > 0:
  25. for (x, y, w, h) in faces:
  26. face_img = img[y:y + h, x:x + w]
  27. face_img_resized = cv2.resize(face_img, (130, 195)) # 保持与应用代码一致
  28. images.append(face_img_resized.flatten())
  29. labels.append(label)
  30. return np.array(images), np.array(labels)
  31. def train_face_recognition_model(dataset_path):
  32. # 加载图像和标签
  33. X, labels = load_images_and_labels(dataset_path)
  34. # 数据集划分
  35. X_train, X_test, y_train, y_test = train_test_split(X, labels, test_size=0.25, random_state=42)
  36. # 特征缩放
  37. scaler = StandardScaler()
  38. X_train_scaled = scaler.fit_transform(X_train)
  39. X_test_scaled = scaler.transform(X_test)
  40. # PCA降维
  41. n_components = 150 # 选择合适的主成分数
  42. pca = PCA(n_components=n_components, whiten=True)
  43. X_train_pca = pca.fit_transform(X_train_scaled)
  44. X_test_pca = pca.transform(X_test_scaled)
  45. # 训练逻辑回归模型
  46. clf = LogisticRegression(C=1e5)
  47. clf.fit(X_train_pca, y_train)
  48. # 预测与评估
  49. y_pred = clf.predict(X_test_pca)
  50. print("Classification Report:")
  51. print(classification_report(y_test, y_pred))
  52. print("Confusion Matrix:")
  53. print(confusion_matrix(y_test, y_pred))
  54. # Eigenfaces进行可视化(可选)
  55. n_components_to_show = 10
  56. """可视化前n个Eigenfaces"""
  57. eigenfaces = pca.components_
  58. eigenface_titles = ["Eigenface %d" % i for i in range(1, n_components_to_show + 1)]
  59. # 选择前n个Eigenfaces进行可视化
  60. for i in range(n_components_to_show):
  61. eigenface = eigenfaces[i].reshape(195, 130) # 根据之前调整的尺寸进行重塑
  62. plt.subplot(2, 5, i + 1)
  63. plt.imshow(eigenface, cmap='gray')
  64. plt.title(eigenface_titles[i])
  65. plt.axis('off') # 不显示坐标轴
  66. plt.show()
  67. # 保存模型与预处理器
  68. dump(clf, 'model.pkl')
  69. dump(scaler, 'scaler.pkl')
  70. dump(pca, 'pca.pkl')
  71. # 调用函数以执行训练流程
  72. train_face_recognition_model(lfw_home)

运行结束后,就会在你的工程目录下创建三个训练好的pkl文件。

然后再创建一个人脸识别用的py文件,代码如下:

  1. import os
  2. from tkinter import Tk, Label, messagebox
  3. import cv2
  4. import joblib
  5. import numpy as np
  6. from PIL import Image, ImageTk
  7. # 加载预先训练好的LogisticRegression模型,用于后续的人脸识别
  8. model = joblib.load('model.pkl')
  9. # 加载特征缩放器,用于标准化输入数据,提高模型识别性能
  10. scaler = joblib.load('scaler.pkl')
  11. # 加载PCA模型,用于降维处理,减少计算复杂度并去除噪声
  12. pca = joblib.load('pca.pkl')
  13. # 定义函数:从给定路径加载参考照片并提取其面部特征
  14. def load_reference_image(reference_path):
  15. # 使用OpenCV读取灰度图像作为参考照片
  16. reference_image = cv2.imread(reference_path, cv2.IMREAD_GRAYSCALE)
  17. # 利用预设的人脸检测器检测参考照片中的人脸
  18. reference_faces = face_cascade.detectMultiScale(reference_image)
  19. # 确保至少检测到一张人脸,否则抛出错误
  20. if len(reference_faces) == 0:
  21. raise ValueError("No face detected in reference image.")
  22. # 获取检测到的第一张人脸区域
  23. reference_face_roi = reference_image[
  24. reference_faces[0][1]:reference_faces[0][1] + reference_faces[0][3],
  25. reference_faces[0][0]:reference_faces[0][0] + reference_faces[0][2]
  26. ]
  27. # 对提取的参考人脸区域进一步预处理,准备用于模型识别
  28. preprocessed_reference_face = preprocess_face(reference_face_roi)
  29. # 返回预处理后的面部特征数据
  30. return preprocessed_reference_face
  31. # 定义函数:预处理输入的人脸图像,以便用于模型识别
  32. def preprocess_face(face_image):
  33. # 确保图像尺寸与训练时一致(130x195)
  34. face_image_resized = cv2.resize(face_image, (130, 195))
  35. # 图像数据展平
  36. img_flattened = face_image_resized.flatten() # 调整尺寸后,直接展平
  37. # 特征缩放
  38. img_scaled = scaler.transform(img_flattened.reshape(1, -1))
  39. # PCA降维
  40. img_pca = pca.transform(img_scaled)
  41. # 使用训练好的模型进行预测
  42. return img_pca
  43. # 定义函数:识别视频流中的脸部并判断是否为目标人物
  44. def recognize_faces(frame):
  45. # 将视频帧转换为灰度图像,便于人脸检测
  46. gray_frame = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
  47. # 使用预定义的人脸级联分类器检测图像中的人脸
  48. face_rects = face_cascade.detectMultiScale(gray_frame, scaleFactor=1.1, minNeighbors=5, minSize=(30, 30))
  49. # 遍历检测到的每一个人脸区域
  50. for (x, y, w, h) in face_rects:
  51. # 提取人脸区域
  52. face_roi = gray_frame[y:y + h, x:x + w]
  53. # 对该人脸区域进行预处理
  54. preprocessed_face = preprocess_face(face_roi)
  55. # 使用模型预测该人脸属于各个类别的概率
  56. probabilities = model.predict_proba(preprocessed_face.reshape(1, -1))[0]
  57. # 获取最可能的预测类别
  58. predicted_label = np.argmax(probabilities)
  59. # 若预测类别与目标人物标签匹配,则认为识别到了目标人物
  60. if predicted_label == target_person_label:
  61. return True
  62. # 若未识别到目标人物,则返回False
  63. return False
  64. # 加载OpenCV预训练的人脸检测模型(基于Haar特征的级联分类器)
  65. base_dir = r"D:\Pythonxiangmu\Python\renlian"
  66. xml_path = os.path.join(base_dir, "haarcascade_frontalface_default.xml")
  67. face_cascade = cv2.CascadeClassifier(xml_path)
  68. # 设置目标人物在模型中的标签假设
  69. target_person_label = 0
  70. # 初始化Tkinter图形界面,用于展示视频流及识别结果
  71. root = Tk()
  72. root.title("Face Recognition System")
  73. root.geometry("800x600")
  74. # 创建一个Label控件用于动态显示视频帧
  75. label = Label(root)
  76. label.pack(fill="both", expand=True)
  77. # 加载并预处理参考照片,获取其特征编码
  78. photo_path = os.path.join(base_dir, "zhaopian.jpg")
  79. reference_face_encoding = load_reference_image(photo_path)
  80. # 定义视频流展示的回调函数,持续更新显示内容并执行人脸识别
  81. def show_frame():
  82. # 从摄像头读取一帧图像
  83. ret, frame = cap.read()
  84. if ret: # 确保成功读取到帧
  85. # 尝试识别当前帧中的人脸
  86. is_recognized = recognize_faces(frame)
  87. # 若识别到目标人物,弹出提示框
  88. if is_recognized:
  89. messagebox.showinfo("Recognition Result", "Face recognized!")
  90. # 转换图像色彩空间以适应Tkinter显示,并调整尺寸
  91. rgb_frame = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)
  92. pil_image = Image.fromarray(rgb_frame)
  93. resized_image = pil_image.resize((root.winfo_width(), root.winfo_height()))
  94. # 转换为Tkinter兼容的图像格式并更新显示
  95. tk_image = ImageTk.PhotoImage(image=resized_image)
  96. label.config(image=tk_image)
  97. label.image = tk_image # 防止图像对象被提前释放
  98. # 定时调用自身以实现连续更新
  99. root.after(1, show_frame)
  100. # 初始化摄像头设备
  101. cap = cv2.VideoCapture(0)
  102. # 启动视频流的显示循环
  103. show_frame()
  104. # 运行Tkinter事件循环
  105. root.mainloop()
  106. # 关闭摄像头资源
  107. cap.release()

运行后就开始人脸识别,这样就完成啦!

注意,代码中的所有的路径都应该改成自己的路径!其中的像素可以修改,但是要注意训练脚本要和识别脚本的像素一致,否则会报错!

如果有什么问题欢迎在评论区提问,也可以发个人邮箱:linyuanda@linyuanda.com

原文链接:https://www.cnblogs.com/python120/p/18162859

 友情链接:直通硅谷  点职佳  北美留学生论坛

本站QQ群:前端 618073944 | Java 606181507 | Python 626812652 | C/C++ 612253063 | 微信 634508462 | 苹果 692586424 | C#/.net 182808419 | PHP 305140648 | 运维 608723728

W3xue 的所有内容仅供测试,对任何法律问题及风险不承担任何责任。通过使用本站内容随之而来的风险与本站无关。
关于我们  |  意见建议  |  捐助我们  |  报错有奖  |  广告合作、友情链接(目前9元/月)请联系QQ:27243702 沸活量
皖ICP备17017327号-2 皖公网安备34020702000426号