0


人工智能大作业——人脸识别系统(最终)

写在前面
时间过得飞快,时间已经距离我发第一篇文章过去2年多了,也不再从事代码工作,偶然间上到csdn翻看文章经过,看到还是有些人关注人脸识别系统的后续的,我猜大概率是学弟学妹们正在被期末实验折磨中,翻了翻原先的代码还能找到就一并更完了吧,如果抄了我的作业记得来学长的评论区表示一下感谢哦(代码完全照抄必被老师发现,别那么傻)。
一、作业要求
  基本任务:开发一个人脸识别系统,要求以ORL人脸数据库为实验数据,构造出一个完整的人脸识别系统,要求有界面,可选择输入单张图像并显示该图像,然后实现该图像的识别,并输出对应的识别结果图像。要求数据库中每个人的5张照片作为训练集,另外5张照片作为测试集,并统计其识别正确率。(实验采用的程序语言不限、人脸识别算法不限)
扩展任务:1、实现一个完整的人脸识别系统,照片自己采集,要求30人以上,实现摄像头与照片两种模式作为输入的人脸检测与识别,正确率要求95%以上。2、实现一个完整的多人人脸识别系统,照片自己采集,要求30人以上,实现摄像头与照片两种模式作为输入的多人脸检测与识别,正确率要求95%以上。
二、算法原理
  基本思路是利用knn算法实现人脸识别,orl数据集的人脸识别系统与自定义数据集的多人人脸识别系统的系统大致逻辑为:模型训练,加载模型查找最邻近解,显示匹配到的信息。
  模型训练过程为利用face_recognition模块识别出人脸位置,加上人脸信息标签后利用sklearn模块进行训练,得到相应的.clf分类器并保存,识别过程为利用保存的分类器进行相邻判断并找到最相邻的解的图像。
  在机器的学习以及图像处理显示方面,调用sklearn、PIL、face_recognition等模块。在界面的展示以及用户的交互上,调用了tkinter模块。
三、人脸识别系统流程图与步骤说明
(一)orl数据集的人脸识别系统 流程图:在这里插入图片描述
步骤说明:
(1)选择训练集路径
在使用该系统前,需要先对人脸图像进行训练,所以首先得先指定训练集的路径位置。注意:训练集路径不能为空,且目录结构应大致为./train/s1/img1 img2 … ./train/s2 ./train/s3/img1 im2 …
(2)训练模型
进行模型训练,提示用户会造成系统卡顿,请耐心等待。
注意:①卡顿属于正常现象,是因为在模型训练过程中需要对大量图片进行处理,需要耐心等待。训练后会生成“trained_knn_model_orl.clf”文件,表示训练后形成的Knn分类器。默认保存路径是与该python文件同级目录下的位置。②训练过后系统会自动读取对应目录下的knn分类器,故下次使用时可不必再次训练。
(3)显示识别准确率
在模型训练完成后会自动对orl数据集中200张人像进行识别匹配进而计算正确率并显示。
(4)选择数据集中的待匹配图像
选择数据集中待匹配的图像进行检测,若格式不正确,系统会给予相应的提示。
(5)输出匹配的图像
从对应的训练集中查找到对应人像的照片进行显示。
(二)自定义数据集的多人人脸识别系统 流程图:
在这里插入图片描述
步骤说明:
(1)选择训练集路径
在使用该系统前,需要先对人脸图像进行训练,所以首先要先指定训练集的路径位置。注意:目录结构应大致为./train/s1/img1 img2 … ./train/s2 ./train/s3/img1 im2 …(这一步流程与上一个系统要求一致,如:目录结构要合理,训练集目录下有n个文件夹表示n个人的训练数据,文件夹名表示人物的名字,目录内的图片文件只能是这个人的单人的照片,否则不会训练成功)
(2)训练模型
进行模型训练,提示用户会造成系统卡顿,请耐心等待。训练后会在于文件同级目录上保存trained_knn_model_manyface_video.clf文件,这样下次使用时系统就会自动利用上面这个分类器进行图像识别。
(3)本地识别多人像照片
按下按钮后,会打开文件管理器,让用户选择一张照片进行识别。系统会利用trained_knn_model_manyface_video.clf这个分类器找出图像中所有人物的头像并利用knn算法匹配与它最相近的人物。之后系统会打开用户选中的图片并在图片上对人物图像加框和显示匹配到人物的名字。
(4)从摄像头识别多人像照片
按下按钮后,会打开摄像头采集用户当前的场景,对场景中的人物进行最近相邻匹配人物,并加框显示识别结果。

四、部分核心代码

  1. 训练模型的算法:
  2. #模型训练,得到分类器,即同级目录下的.clf文件
  3. def train_model(train_dir):
  4. #指定KNN算法训练后分类器的文件名
  5. model_save_path = "trained_knn_model_orl.clf"
  6. X = []
  7. y = []
  8. #flag变量用于判断训练集的有效性
  9. flag=False
  10. # 对训练集中每个人的目录进行遍历,如C:/Users/Haifeng/OneDrive/桌面/face_identity_orl/knn_examples_orl2/train\s1..s2..s3....
  11. for class_dir in os.listdir(train_dir):
  12. #判断当前路径是目录,若s1 s2 s3 不是目录是文件则抛弃
  13. if not os.path.isdir(os.path.join(train_dir, class_dir)):
  14. continue
  15. #对图像进行格式转换,转成jpg格式的图像,便于训练
  16. bmpTojpg(os.path.join(train_dir, class_dir))
  17. # 对每个人的图像进行遍历
  18. for img_path in image_files_in_folder(os.path.join(train_dir, class_dir)):
  19. # 将图片导入到numpy数组中
  20. image = face_recognition.load_image_file(img_path)
  21. # 查找图片中人脸(上下左右)的位置,图像中可能有多个人脸 face_locations的值类似[(135,536,198,474),()]
  22. face_bounding_boxes = face_recognition.face_locations(image)
  23. #若训练集中的图像只存在一张人脸,说明这是张合格的训练集,则加入集合进一步处理
  24. if len(face_bounding_boxes) == 1:
  25. #只要有一张脸被训练到,即为训练成功
  26. flag=True
  27. # 将现在图像的脸部编码加载到训练集中
  28. X.append(face_recognition.face_encodings(image, known_face_locations=face_bounding_boxes)[0])
  29. y.append(class_dir)
  30. # X加的是这个图像和人脸的位置Y加的是图像外面的文件夹名字
  31. # 创建并训练KNN分类器
  32. knn_clf = neighbors.KNeighborsClassifier(n_neighbors=2, algorithm='ball_tree', weights='distance')
  33. knn_clf.fit(X, y)
  34. # 以保存路径的格式要求保存分类器
  35. if model_save_path is not None:
  36. with open(model_save_path, 'wb') as f:
  37. pickle.dump(knn_clf, f)
  38. #人脸预测匹配,根据传入的图像路径,进行人脸的匹配,返回匹配到人物的名字,以及原图像中相应的人脸坐标,以及是否存在匹配的人脸
  39. def predict(X_img_path):
  40. #读入knn_clf模型
  41. if knn_clf is None:
  42. with open(model_path, 'rb') as f:
  43. knn_clf = pickle.load(f)
  44. # 加载图像和找到脸的位置
  45. X_img = face_recognition.load_image_file(X_img_path)
  46. X_face_locations = face_recognition.face_locations(X_img)
  47. # 如果在图像中没有找到脸,则返回一个空集
  48. if len(X_face_locations) == 0:
  49. return []
  50. # 将待测图片进行编码
  51. faces_encodings = face_recognition.face_encodings(X_img, known_face_locations=X_face_locations)
  52. # 使用knn模型对最优的解进行匹配
  53. closest_distances = knn_clf.kneighbors(faces_encodings, n_neighbors=1)
  54. are_matches = [closest_distances[0][i][0] <= distance_threshold for i in range(len(X_face_locations))]
  55. # 返回相应格式的类,分别为[[name1,name2],(上下左右位置坐标),人脸位置]
  56. return [(pred, loc) if rec else ("unknown", loc) for pred, loc, rec in zip(knn_clf.predict(faces_encodings), X_face_locations, are_matches)]

五、界面展示

orl数据集的人脸识别系统
在这里插入图片描述
在这里插入图片描述
自定义数据集的多人人脸识别系统
在这里插入图片描述
在这里插入图片描述
六、源代码(千万不要照抄!千万不要照抄!千万不要照抄!)
(一)orl_face.py

  1. #!/usr/bin/env python
  2. # -*- coding:utf-8 -*-
  3. import tkinter as tk
  4. import tkinter.filedialog
  5. from PIL import Image, ImageTk #调用图片处理模块,保证png后缀名可用
  6. import tkinter.messagebox
  7. import pickle
  8. import math
  9. from sklearn import neighbors
  10. import os
  11. import os.path
  12. import pickle
  13. from PIL import Image, ImageDraw
  14. import face_recognition
  15. from face_recognition.face_recognition_cli import image_files_in_folder
  16. #设置可支持的图片类型
  17. ALLOWED_EXTENSIONS = {'bmp','png', 'jpg', 'jpeg'}
  18. #将该路径下所有.bmp图像转换为.jpg图像
  19. def bmpTojpg(dir_path):
  20. for fileName in os.listdir(dir_path):
  21. file_path=os.path.join(dir_path,fileName)
  22. if os.path.split(file_path)[-1].split(".")[-1] != 'bmp':
  23. continue
  24. newFileName = fileName[0:fileName.find(".bmp")] + ".jpg"
  25. im = Image.open(file_path)
  26. rgb = im.convert('RGB') # 灰度转RGB
  27. rgb.save(dir_path + "\\" + newFileName)
  28. os.remove(file_path)
  29. # command = "del " + dir_path + "\\*.bmp"
  30. # os.system(command)
  31. # os.remove(dir_path+"\\*.bmp")
  32. #人脸识别核心算法,通过传入数据集图像,通过训练得到的knn分类器进行人脸匹配
  33. def predict(X_img_path, knn_clf=None, model_path=None, distance_threshold=0.6):
  34. # 读取knn分类器
  35. if knn_clf is None:
  36. with open(model_path, 'rb') as f:
  37. knn_clf = pickle.load(f)
  38. # 加载图像文件
  39. X_img = face_recognition.load_image_file(X_img_path)
  40. #寻找人脸特征
  41. X_face_locations = face_recognition.face_locations(X_img)
  42. # 如果没有人脸特征,则返回空集
  43. if len(X_face_locations) == 0:
  44. return [("unknown", (0,0,0,0))]
  45. # 为数据集人脸编码
  46. faces_encodings = face_recognition.face_encodings(X_img, known_face_locations=X_face_locations)
  47. # 使用knn模型匹配最优的人脸
  48. closest_distances = knn_clf.kneighbors(faces_encodings, n_neighbors=1)
  49. are_matches = [closest_distances[0][i][0] <= distance_threshold for i in range(len(X_face_locations))]
  50. # 返回人脸的位置信息和对应人的姓名并删除不在阈值内的分类
  51. return [(pred, loc) if rec else ("unknown", loc) for pred, loc, rec in zip(knn_clf.predict(faces_encodings), X_face_locations, are_matches)]
  52. #获取目录
  53. def askdirectory():
  54. dir_path=tk.filedialog.askdirectory()
  55. path.set(dir_path)
  56. #模型训练
  57. def train_model(train_dir):
  58. # print(dir_path)
  59. # print("Training KNN classifier...")
  60. #对训练集路径的合法性进行判断并给出提示
  61. if not os.path.isdir(train_dir):
  62. tk.messagebox.showerror(title="路径错误", message="训练模型路径不能为空")
  63. return
  64. #与用户交互
  65. if not tk.messagebox.askyesno(title="系统提示", message="模型训练会导致系统卡顿10~15s\n\t请耐心等待"):
  66. return
  67. #指定KNN算法训练后分类器的文件名
  68. model_save_path = "trained_knn_model_orl.clf"
  69. X = []
  70. y = []
  71. #flag变量用于判断训练集的有效性
  72. flag=False
  73. # 对训练集中每个人的目录进行遍历,如C:/Users/杨海丰/OneDrive/桌面/face_identity_orl/knn_examples_orl2/train\s1..s2..s3....
  74. for class_dir in os.listdir(train_dir):
  75. #判断当前路径是目录,若s1 s2 s3 不是目录是文件则抛弃
  76. if not os.path.isdir(os.path.join(train_dir, class_dir)):
  77. continue
  78. #对图像进行格式转换,转成jpg格式的图像,便于训练
  79. bmpTojpg(os.path.join(train_dir, class_dir))
  80. # 对每个人的图像进行遍历
  81. for img_path in image_files_in_folder(os.path.join(train_dir, class_dir)):
  82. # 将图片导入到numpy数组中
  83. image = face_recognition.load_image_file(img_path)
  84. # 查找图片中人脸(上下左右)的位置,图像中可能有多个人脸 face_locations的值类似[(135,536,198,474),()]
  85. face_bounding_boxes = face_recognition.face_locations(image)
  86. #若训练集中的图像只存在一张人脸,说明这是张合格的训练集,则加入集合进一步处理
  87. if len(face_bounding_boxes) == 1:
  88. #只要有一张脸被训练到,即为训练成功
  89. flag=True
  90. # 将现在图像的脸部编码加载到训练集中
  91. X.append(face_recognition.face_encodings(image, known_face_locations=face_bounding_boxes)[0])
  92. y.append(class_dir)
  93. # X加的是这个图像和人脸的位置 Y加的是图像外面的文件夹名字
  94. #若训练集中一张人脸也没有检测到,则提示用户更换训练集
  95. if not flag:
  96. tk.messagebox.showerror(title="训练集错误", message="训练集有误,请更换训练集")
  97. return
  98. # 创建并训练KNN分类器
  99. knn_clf = neighbors.KNeighborsClassifier(n_neighbors=2, algorithm='ball_tree', weights='distance')
  100. knn_clf.fit(X, y)
  101. # 以保存路径的格式要求保存分类器
  102. if model_save_path is not None:
  103. with open(model_save_path, 'wb') as f:
  104. pickle.dump(knn_clf, f)
  105. #默认检测正确率时orl未训练的后200张照片位于与train目录同级下的test文件夹中
  106. test_dir = os.path.join(os.path.split(train_dir)[0],'test')
  107. print(test_dir)
  108. # 计算识别的正确率
  109. correct=sum=0.0
  110. for class_dir in os.listdir(test_dir):
  111. # 判断当前路径是目录,若s1 s2 s3 不是目录是文件则抛弃
  112. if not os.path.isdir(os.path.join(test_dir, class_dir)):
  113. continue
  114. # 对图像进行格式转换,转成jpg格式的图像,便于训练
  115. bmpTojpg(os.path.join(test_dir, class_dir))
  116. for img_path in image_files_in_folder(os.path.join(test_dir, class_dir)):
  117. sum=sum+1
  118. predictions = predict(img_path, model_path="trained_knn_model_orl.clf")
  119. for name, (top, right, bottom, left) in predictions:
  120. if name==class_dir:
  121. correct=correct+1
  122. break;
  123. #显示准确率信息
  124. tk.Label(window, font=('Arial', 16), text="准确率:{}".format(correct/sum)).grid(row=7, column=4, columnspan=1)
  125. #与用户进行交互
  126. tk.messagebox.showinfo(title="信息",message="训练已完成,可识别人脸")
  127. # print("Training complete!")
  128. #人脸识别,利用训练好的knn分类器进行orl人脸的识别
  129. def recog_orl_face(train_path):
  130. #打开文件筛选器筛选文件
  131. img_path=tk.filedialog.askopenfilename()
  132. #判断是否选中的文件为一张图片,如果是则打开并显示,否则与用户进行交互
  133. try:
  134. img1=Image.open(img_path)
  135. photo1 = ImageTk.PhotoImage(img1)
  136. img_label1.config(imag=photo1)
  137. # tkinter.update()
  138. img_label1.image = photo1
  139. except:
  140. tk.messagebox.showerror(title="图片格式有误", message="图片格式有误,请选择一张图片")
  141. return
  142. #进行人脸预测,img_path是数据集中人脸的路径,model_path是训练后得到的KNN分类器
  143. predictions = predict(img_path, model_path="trained_knn_model_orl.clf")
  144. # print(predictions)
  145. #对人脸进行识别
  146. for name, (top, right, bottom, left) in predictions:
  147. # print(name)
  148. #如果该照片未找到匹配的图像,则提示用户 匹配失败
  149. if(name=="unknown"):
  150. tk.messagebox.showerror(title="匹配失败", message="未找到匹配的人脸图像")
  151. img_label1.grid_forget()
  152. else:
  153. try:
  154. # 从训练集中找一张对应识别任务的图像打开并显示
  155. testphoto_dir = os.path.join(train_path, name)
  156. # print(testphoto_dir)
  157. testphoto_path = os.path.join(testphoto_dir, os.listdir(testphoto_dir)[0])
  158. # print(testphoto_path)
  159. img2 = Image.open(testphoto_path)
  160. photo2 = ImageTk.PhotoImage(img2)
  161. img_label2.config(imag=photo2)
  162. # tkinter.update()
  163. img_label2.image = photo2
  164. except:
  165. tk.messagebox.showerror(title="训练集路径有误", message="\t\t匹配成功\n但训练集路径选择错误,导致系统无法显示对应人物图像")
  166. break;
  167. #主程序入口
  168. if __name__ == "__main__":
  169. # 建立窗口window
  170. window = tk.Tk()
  171. # 给窗口的可视化起名字
  172. window.title('ORL人脸识别系统')
  173. # 设定窗口的大小(长 * 宽)
  174. window.geometry('400x250')
  175. path = tk.StringVar()
  176. #添加Label标签
  177. tk.Label(window, font=('Arial', 14), text="训练集的路径").grid(row=0, column=1, columnspan=2)
  178. #添加Entry输入框,用于显示用户载入的训练集路径
  179. entry_dir=tk.Entry(window,textvariable=path)
  180. entry_dir.grid(row=0, column=3, columnspan=3)
  181. #添加 选择路径、训练模型 2个按钮
  182. tk.Button(window, font=('Arial', 12), text="选择路径", command=askdirectory).grid(row=0, column=6)
  183. tk.Button(window, font=('Arial', 12), text="训练模型",command=lambda:train_model(entry_dir.get())).grid(row=2, column=4)
  184. # 添加2个Label标签用来当做放置图片的位置,一个是显示待识别的图像,一个是显示识别后结果的图像
  185. img_label1 = tk.Label(window)
  186. img_label1.grid(row=4,column=1,rowspan=3, columnspan=2,padx=4, pady=20)
  187. img_label2 = tk.Label(window)
  188. img_label2.grid(row=4, column=5, rowspan=3, columnspan=2, padx=4, pady=20)
  189. #添加 选择人像并识别的按钮
  190. tk.Button(window, font=('Arial', 12), text="选择人像并识别", command=lambda: recog_orl_face(entry_dir.get())).grid(row=5,
  191. column=3,
  192. columnspan=2)
  193. # 主窗口循环显示
  194. window.mainloop()

(二)multi_face.py

  1. #!/usr/bin/env python
  2. import tkinter as tk
  3. import tkinter.filedialog
  4. from PIL import Image, ImageTk#调用图片处理模块,保证png后缀名可用
  5. import tkinter.messagebox
  6. import pickle
  7. import math
  8. from sklearn import neighbors
  9. import os
  10. import os.path
  11. import pickle
  12. from PIL import Image, ImageDraw
  13. import face_recognition
  14. from face_recognition.face_recognition_cli import image_files_in_folder
  15. import cv2
  16. import numpy as np
  17. #将该路径下所有.bmp图像转换为.jpg图像
  18. def bmpTojpg(dir_path):
  19. for fileName in os.listdir(dir_path):
  20. file_path=os.path.join(dir_path,fileName)
  21. if os.path.split(file_path)[-1].split(".")[-1] != 'bmp':
  22. continue
  23. newFileName = fileName[0:fileName.find(".bmp")] + ".jpg"
  24. im = Image.open(file_path)
  25. rgb = im.convert('RGB') # 灰度转RGB
  26. rgb.save(dir_path + "\\" + newFileName)
  27. os.remove(file_path)
  28. # 使得识别结果可视化,即将图像以图片形式打开,且在人像上加框
  29. def show_prediction_labels_on_image(img_path, predictions):
  30. pil_image = Image.open(img_path).convert("RGB")
  31. draw = ImageDraw.Draw(pil_image)
  32. for name, (top, right, bottom, left) in predictions:
  33. # 利用pillow模块在图片上画一个矩形
  34. draw.rectangle(((left, top), (right, bottom)), outline=(255, 0, 0),width=3)
  35. #字符编码设置为utf-8
  36. name = name.encode("UTF-8")
  37. text_width, text_height = draw.textsize(name)
  38. draw.rectangle(((left, bottom - text_height - 10), (right, bottom)), fill=(0,0,0),outline=(255, 0, 0),width=3)
  39. draw.text((left + 6, bottom - text_height - 5), name, fill=(255, 255, 255, 255))
  40. # 从内存中移除pillow库
  41. del draw
  42. # 显示结果
  43. pil_image.show()
  44. #模型训练
  45. def train_model(train_dir):
  46. # print(dir_path)
  47. # print("Training KNN classifier...")
  48. #对训练集路径的合法性进行判断并给出提示
  49. if not os.path.isdir(train_dir):
  50. tk.messagebox.showerror(title="路径错误", message="训练模型路径不能为空")
  51. return
  52. #与用户交互
  53. if not tk.messagebox.askyesno(title="系统提示", message="模型训练会导致系统卡顿10~15s\n\t请耐心等待"):
  54. return
  55. #指定KNN算法训练后分类器的文件名
  56. model_save_path = "trained_knn_model_manyface_video.clf"
  57. X = []
  58. y = []
  59. #flag变量用于判断训练集的有效性
  60. flag=False
  61. print(train_dir)
  62. # 对训练集中每个人的目录进行遍历,如C:/Users/杨海丰/OneDrive/桌面/face_identity_orl/knn_examples_orl2/train\s1..s2..s3....
  63. for class_dir in os.listdir(train_dir):
  64. #判断当前路径是目录,若s1 s2 s3 不是目录是文件则抛弃
  65. if not os.path.isdir(os.path.join(train_dir, class_dir)):
  66. continue
  67. #对图像进行格式转换,转成jpg格式的图像,便于训练
  68. bmpTojpg(os.path.join(train_dir, class_dir))
  69. # 对每个人的图像进行遍历
  70. for img_path in image_files_in_folder(os.path.join(train_dir, class_dir)):
  71. # 将图片导入到numpy数组中
  72. image = face_recognition.load_image_file(img_path)
  73. # 查找图片中人脸(上下左右)的位置,图像中可能有多个人脸 face_locations的值类似[(135,536,198,474),()]
  74. face_bounding_boxes = face_recognition.face_locations(image)
  75. #若训练集中的图像只存在一张人脸,说明这是张合格的训练集,则加入集合进一步处理
  76. if len(face_bounding_boxes) == 1:
  77. #只要有一张脸被训练到,即为训练成功
  78. flag=True
  79. # 将现在图像的脸部编码加载到训练集中
  80. X.append(face_recognition.face_encodings(image, known_face_locations=face_bounding_boxes)[0])
  81. y.append(class_dir)
  82. # X加的是这个图像和人脸的位置 Y加的是图像外面的文件夹名字
  83. #若训练集中一张人脸也没有检测到,则提示用户更换训练集
  84. if not flag:
  85. tk.messagebox.showerror(title="训练集错误", message="训练集有误,请更换训练集")
  86. return
  87. # 创建并训练KNN分类器
  88. knn_clf = neighbors.KNeighborsClassifier(n_neighbors=2, algorithm='ball_tree', weights='distance')
  89. knn_clf.fit(X, y)
  90. # 以保存路径的格式要求保存分类器
  91. if model_save_path is not None:
  92. with open(model_save_path, 'wb') as f:
  93. pickle.dump(knn_clf, f)
  94. tk.messagebox.showinfo(title="信息",message="训练已完成,可进行人脸识别")
  95. # print("Training complete!")
  96. #人脸预测
  97. def predict(X_img_path, knn_clf=None, model_path=None, distance_threshold=0.6):
  98. #读入knn_clf模型
  99. if knn_clf is None:
  100. with open(model_path, 'rb') as f:
  101. knn_clf = pickle.load(f)
  102. # print(X_img_path)
  103. # 加载图像和找到脸的位置
  104. X_img = face_recognition.load_image_file(X_img_path)
  105. X_face_locations = face_recognition.face_locations(X_img)
  106. # 如果在图像中没有找到脸,则返回一个空集
  107. if len(X_face_locations) == 0:
  108. return []
  109. # 将待测图片进行编码
  110. faces_encodings = face_recognition.face_encodings(X_img, known_face_locations=X_face_locations)
  111. # 使用knn模型对最优的解进行匹配
  112. closest_distances = knn_clf.kneighbors(faces_encodings, n_neighbors=1)
  113. are_matches = [closest_distances[0][i][0] <= distance_threshold for i in range(len(X_face_locations))]
  114. # 返回相应格式的类,分别为[[name1,name2],(上下左右位置坐标),人脸位置]
  115. return [(pred, loc) if rec else ("unknown", loc) for pred, loc, rec in zip(knn_clf.predict(faces_encodings), X_face_locations, are_matches)]
  116. #获取目录
  117. def askdirectory():
  118. dir_path=tk.filedialog.askdirectory()
  119. path.set(dir_path)
  120. #从照片识别多人人脸
  121. def recog_many_face():
  122. img_path = tk.filedialog.askopenfilename()
  123. # 判断是否选中的文件为一张图片,如果是则打开并显示,否则与用户进行交互
  124. try:
  125. img1 = Image.open(img_path)
  126. except:
  127. tk.messagebox.showerror(title="图片格式有误", message="图片格式有误,请选择一张图片")
  128. return
  129. # 进行人脸预测,img_path是数据集中人脸的路径,model_path是训练后得到的KNN分类器
  130. predictions = predict(img_path, model_path="trained_knn_model_manyface_video.clf")
  131. # print(predictions)
  132. # 对人脸进行识别
  133. show_prediction_labels_on_image(img_path, predictions)
  134. #从摄像头进行认脸
  135. def recog_from_video(train_dir,knn_clf=None):
  136. #读入knn训练模型
  137. model_path = "trained_knn_model_manyface_video.clf"
  138. if knn_clf is None:
  139. with open(model_path, 'rb') as f:
  140. knn_clf = pickle.load(f)
  141. # 开启摄像头
  142. camera = cv2.VideoCapture(0)
  143. while True:
  144. # 抽一帧作为检测人脸的图像
  145. ret, frame = camera.read()
  146. # 将图像转换为rgb图像
  147. rgb_frame = frame[:, :, ::-1]
  148. # 处理得到所有人脸的位置与编码信息
  149. face_locations = face_recognition.face_locations(rgb_frame)
  150. faces_encodings = face_recognition.face_encodings(rgb_frame, face_locations)
  151. #异常处理,如果得到的人脸为空,则跳出取下一张
  152. if faces_encodings == []:
  153. continue
  154. #求与多人脸相对应最优的匹配人脸
  155. closest_distances = knn_clf.kneighbors(faces_encodings, n_neighbors=1)
  156. are_matches = [closest_distances[0][i][0] <= 0.53 for i in range(len(face_locations))]
  157. #显示人脸信息,name表示该人的名字,第二个参数是检测到人脸的位置信息,rec表示是否有匹配到的最优解,如果不为空,则必有人脸被匹配到
  158. for name, (top, right, bottom, left), rec in zip(knn_clf.predict(faces_encodings), face_locations, are_matches):
  159. if not rec:
  160. name = "unknown"
  161. print(name)
  162. print(name)
  163. #画框
  164. cv2.rectangle(frame, (left, top), (right, bottom), (0, 0, 255), 2)
  165. cv2.rectangle(frame, (left, bottom - 35), (right, bottom), (0, 0, 255), cv2.FILLED)
  166. font = cv2.FONT_HERSHEY_DUPLEX
  167. cv2.putText(frame, name, (left + 6, bottom - 6), font, 0.8, (255, 255, 255), 1)
  168. cv2.imshow('multi_face_recognition', frame)
  169. # 按q键退出人脸检测
  170. if cv2.waitKey(1) & 0xFF == ord('q'):
  171. break
  172. camera.release()
  173. cv2.destroyAllWindows()
  174. if __name__ == "__main__":
  175. # 建立窗口window
  176. window = tk.Tk()
  177. # 给窗口的可视化起名字
  178. window.title('多人脸识别系统')
  179. # 设定窗口的大小(长 * 宽)
  180. window.geometry('450x180')
  181. path = tk.StringVar()
  182. #添加Label标签
  183. tk.Label(window, font=('Arial', 14), text="训练集的路径").grid(row=0, column=1, columnspan=2)
  184. #添加Entry输入框,用于显示用户载入的训练集路径
  185. entry_dir=tk.Entry(window,textvariable=path)
  186. entry_dir.grid(row=0, column=3, columnspan=3)
  187. #添加 选择路径、训练模型 2个按钮
  188. tk.Button(window, font=('Arial', 12), text="选择路径", command=askdirectory).grid(row=0, column=6)
  189. tk.Button(window, font=('Arial', 12), text="训练模型",command=lambda:train_model(entry_dir.get())).grid(row=2, column=4)
  190. #添加 选择人像并识别的按钮
  191. tk.Button(window, font=('Arial', 12), text="本地识别多人像照片", command=lambda: recog_many_face()).grid(row=5,
  192. column=1,
  193. columnspan=2)
  194. tk.Button(window, font=('Arial', 12), text="从摄像头识别多人人像", command=lambda: recog_from_video(entry_dir.get())).grid(row=5,
  195. column=5,
  196. columnspan=2)
  197. tk.Label(window, font=('Arial', 14)).grid(row=3)
  198. tk.Label(window, font=('Arial', 14)).grid(row=4)
  199. # 主窗口循环显示
  200. window.mainloop()

代码可能未能完全实现全部功能,交差是没问题的,但是具体什么问题也忘记了,训练和测试数据集本想一并上传,但gitee的ssh安全配置出了点问题上报不了,如果还有机会到时候会贴在评论区。
写在最后:大学四年是一段美好而短暂的时光,原先没有疫情的学习生活可能会更加多彩,但这丝毫不影响这四年的轻松与愉悦。工作后常常会想起在大学的时光,那时至少没有生活的压力,不知道屏幕前的你是什么感受,好好珍惜,仅以此篇为早以结束的大学生活画上再一个句号。


本文转载自: https://blog.csdn.net/qq_41745118/article/details/127823863
版权归原作者 小平我自豪 所有, 如有侵权,请联系我们删除。

“人工智能大作业——人脸识别系统(最终)”的评论:

还没有评论