当前位置:   article > 正文

从零开始实现戴口罩人脸表情识别:基于Xception模型的深度学习应用_表情识别模型

表情识别模型

目录

一、简介:

二、数据集来源与详情

来源

详细处理

三、模型介绍(Xception)

三、技术路线

1.PaddleClas简介

2、模型库链接:

四、环境配置

五、模型训练

配置训练参数文件(已为大家提供参考参数文件)

训练

加载训练可视化

六、模型预测

七、模型导出


一、简介:

在这篇博客文章中,我们将深入探讨如何从头开始,利用深度学习模型Xception来实现戴口罩人脸表情识别的挑战。这个问题在当今社会中尤其具有现实意义,因为全球公众面临着新冠病毒的威胁,口罩成为我们日常生活的必备之物,而在戴口罩的情况下识别人脸表情具有许多重要的应用价值,如提升社交软件的用户体验,提高公共场所的安全等。

我们将从基础开始,解释Xception模型的工作原理,然后详细阐述如何使用该模型进行戴口罩人脸表情识别的训练与实现。文章内容将包括数据收集、数据预处理、模型训练、优化,以及模型测试的详细步骤。

无论你是一位有经验的深度学习研究者,还是对人工智能应用感兴趣的初学者,我们都相信你将在这篇文章中找到新的知识和灵感。希望通过我们的介绍,你能更好地理解并应用深度学习技术,解决实际生活中的问题。

二、数据集来源与详情


来源

本项目基于fer2013人脸表情数据集,它于2013年国际机器学习会议(ICML)上推出,并成为比较表情识别模型性能的基准之一,同时也作为了2013年Kaggle人脸识别比赛的数据。Fer2013包含28709张训练集图像、3589张公开测试集图像和3589张私有测试集图像,每张图像为4848大小的灰度图片,如下图所示。Fer2013数据集中由有生气(angry)、厌恶(disgust)、恐惧(fear)、开心(happy)、难过(sad)、惊讶(surprise)和中性(neutral)七个类别组成。由于这个数据集大多是通过爬虫在互联网上进行爬取所得,因此存在一定的误差性。

本项目使用face-mask对人脸添加口罩,简单介绍一下face-mask是基于dlib和face_recognition两大人脸检测的库实现的人脸关键点检测的方法。处理完成后共得到11870张训练集,3016张测试集(原数据集存在一些不能被face-mask所识别到的人脸)。经过实验发现sad、disgust、anger眼部特征十分相识,因此本试验只进行对anger、fear、happy、surprise的分类。

详细处理

  • 安装face-mask 在安装之前要先配置dlib,具体过程请大家自行探索。
pip install face-mask
  • 关键代码
  1. # -*- coding: utf-8 -*-
  2. import os
  3. import numpy as np
  4. from PIL import Image, ImageFile
  5. __version__ = '0.3.0'
  6. IMAGE_DIR = os.path.join(os.path.dirname(os.path.abspath(__file__)), 'images')
  7. DEFAULT_IMAGE_PATH = os.path.join(IMAGE_DIR, 'default-mask.png')
  8. BLACK_IMAGE_PATH = os.path.join(IMAGE_DIR, 'black-mask.png')
  9. BLUE_IMAGE_PATH = os.path.join(IMAGE_DIR, 'blue-mask.png')
  10. RED_IMAGE_PATH = os.path.join(IMAGE_DIR, 'red-mask.png')
  11. class FaceMasker:
  12. KEY_FACIAL_FEATURES = ('nose_bridge', 'chin')
  13. def __init__(self, face_path, mask_path, show=False, model='hog'):
  14. self.face_path = face_path
  15. self.mask_path = mask_path
  16. self.show = show
  17. self.model = model
  18. self._face_img: ImageFile = None
  19. self._mask_img: ImageFile = None
  20. def mask(self):
  21. import face_recognition
  22. face_image_np = face_recognition.load_image_file(self.face_path)
  23. face_locations = face_recognition.face_locations(face_image_np, model=self.model)
  24. face_landmarks = face_recognition.face_landmarks(face_image_np, face_locations)
  25. self._face_img = Image.fromarray(face_image_np)
  26. self._mask_img = Image.open(self.mask_path)
  27. found_face = False
  28. for face_landmark in face_landmarks:
  29. # check whether facial features meet requirement
  30. skip = False
  31. for facial_feature in self.KEY_FACIAL_FEATURES:
  32. if facial_feature not in face_landmark:
  33. skip = True
  34. break
  35. if skip:
  36. continue
  37. # mask face
  38. found_face = True
  39. self._mask_face(face_landmark)
  40. if found_face:
  41. if self.show:
  42. self._face_img.show()
  43. # save
  44. self._save()
  45. else:
  46. print('Found no face.')
  47. def _mask_face(self, face_landmark: dict):
  48. nose_bridge = face_landmark['nose_bridge']
  49. nose_point = nose_bridge[len(nose_bridge) * 1 // 4]
  50. nose_v = np.array(nose_point)
  51. chin = face_landmark['chin']
  52. chin_len = len(chin)
  53. chin_bottom_point = chin[chin_len // 2]
  54. chin_bottom_v = np.array(chin_bottom_point)
  55. chin_left_point = chin[chin_len // 8]
  56. chin_right_point = chin[chin_len * 7 // 8]
  57. # split mask and resize
  58. width = self._mask_img.width
  59. height = self._mask_img.height
  60. width_ratio = 1.2
  61. new_height = int(np.linalg.norm(nose_v - chin_bottom_v))
  62. # left
  63. mask_left_img = self._mask_img.crop((0, 0, width // 2, height))
  64. mask_left_width = self.get_distance_from_point_to_line(chin_left_point, nose_point, chin_bottom_point)
  65. mask_left_width = int(mask_left_width * width_ratio)
  66. mask_left_img = mask_left_img.resize((mask_left_width, new_height))
  67. # right
  68. mask_right_img = self._mask_img.crop((width // 2, 0, width, height))
  69. mask_right_width = self.get_distance_from_point_to_line(chin_right_point, nose_point, chin_bottom_point)
  70. mask_right_width = int(mask_right_width * width_ratio)
  71. mask_right_img = mask_right_img.resize((mask_right_width, new_height))
  72. # merge mask
  73. size = (mask_left_img.width + mask_right_img.width, new_height)
  74. mask_img = Image.new('RGBA', size)
  75. mask_img.paste(mask_left_img, (0, 0), mask_left_img)
  76. mask_img.paste(mask_right_img, (mask_left_img.width, 0), mask_right_img)
  77. # rotate mask
  78. angle = np.arctan2(chin_bottom_point[1] - nose_point[1], chin_bottom_point[0] - nose_point[0])
  79. rotated_mask_img = mask_img.rotate(angle, expand=True)
  80. # calculate mask location
  81. center_x = (nose_point[0] + chin_bottom_point[0]) // 2
  82. center_y = (nose_point[1] + chin_bottom_point[1]) // 2
  83. offset = mask_img.width // 2 - mask_left_img.width
  84. radian = angle * np.pi / 180
  85. box_x = center_x + int(offset * np.cos(radian)) - rotated_mask_img.width // 2
  86. box_y = center_y + int(offset * np.sin(radian)) - rotated_mask_img.height // 2
  87. # add mask
  88. self._face_img.paste(mask_img, (box_x, box_y), mask_img)
  89. def _save(self):
  90. path_splits = os.path.splitext(self.face_path)
  91. new_face_path = path_splits[0] + '-with-mask' + path_splits[1]
  92. self._face_img.save(new_face_path)
  93. print(f'Save to {new_face_path}')
  94. @staticmethod
  95. def get_distance_from_point_to_line(point, line_point1, line_point2):
  96. distance = np.abs((line_point2[1] - line_point1[1]) * point[0] +
  97. (line_point1[0] - line_point2[0]) * point[1] +
  98. (line_point2[0] - line_point1[0]) * line_point1[1] +
  99. (line_point1[1] - line_point2[1]) * line_point1[0]) / \
  100. np.sqrt((line_point2[1] - line_point1[1]) * (line_point2[1] - line_point1[1]) +
  101. (line_point1[0] - line_point2[0]) * (line_point1[0] - line_point2[0]))
  102. return int(distance)
  103. if __name__ == '__main__':
  104. FaceMasker("./face/1.jpg", DEFAULT_IMAGE_PATH, True, 'hog').mask()
推荐阅读
相关标签
  

闽ICP备14008679号