口罩检测一之数据集准备

实现效果:

  1. 在图像中检测是否佩戴口罩
  2. 实时视频流中的口罩检测

构建数据集:

在这里收集戴口罩照片比较麻烦,可以使用openCV在人脸上贴上口罩构建数据集,具体实现方法如下:
注:有真实的口罩数据集会比较好,这需要去搜集大量带口罩的数据集

  1. 传入一个人脸图像的文件夹以及背景透明的口罩图片
face_folder_path =r"F:\AI\Ai_env\CV\case\face_mask\examples" 
mask_path = r"F:\AI\Ai_env\CV\case\face_mask\Data_Generator\mask_mode\mask.png"
#获取每个人脸图像的地址
images = [os.path.join(folder_path, f) for f in os.listdir(folder_path) if os.path.isfile(os.path.join(folder_path, f))]
for i in range(len(images)):
	face_path =  images[i]
  1. 查看是否具有需要的面部特征的图像,没有的话跳过不进行口罩贴图,为了设置口罩的大小,以及贴口罩的位置,需要定位面部特征点,需要的面部特征,“nose_bridge”、“chin”
       KEY_FACIAL_FEATURES = ('nose_bridge', 'chin')
       face_image_np = face_recognition.load_image_file(face_path)
       #“hog”CPUs上运行快,但准确率相对低些
       face_locations = face_recognition.face_locations(face_image_np, model=“hog”)
       face_landmarks = face_recognition.face_landmarks(face_image_np, face_locations)
       # 实现array到image的转换,返回image
       face_img = Image.fromarray(face_image_np)
       mask_img = Image.open(mask_path)
        found_face = False
        for face_landmark in face_landmarks:
            # 检查是否包含自定义的面部特征
            skip = False
            for facial_feature in :KEY_FACIAL_FEATURES:
                if facial_feature not in face_landmark:
                    skip = True
                    break
            if skip:
                continue
            found_face = True
            mask_face(face_landmark)

        if found_face:
            if self.show:
                ace_img.show()
           save()
        else:
         break
  1. 定义函数mask_face 进行口罩贴图,根据特征点的位置,计算出口罩需要拉伸以及旋转的位置,利用rotate对图像进行旋转:
  2. 在这里插入图片描述
    代码如下
   def mask_face(self, face_landmark: dict):
        nose_bridge = face_landmark['nose_bridge']
        nose_point = nose_bridge[1]
        nose_v = np.array(nose_point)

        chin = face_landmark['chin']
        chin_len = len(chin)
        chin_bottom_point = chin[8]
        chin_bottom_v = np.array(chin_bottom_point)
        chin_left_point = chin[2]
        chin_right_point = chin[16]

        # 拆分口罩调整大小
        width = self._mask_img.width
        height = self._mask_img.height
        width_ratio = 1.2
        new_height = int(np.linalg.norm(nose_v - chin_bottom_v))

   
        mask_left_img = self._mask_img.crop((0, 0, width // 2, height))
        mask_left_width = self.get_distance_from_point_to_line(chin_left_point, nose_point, chin_bottom_point)
        mask_left_width = int(mask_left_width * width_ratio)
        mask_left_img = mask_left_img.resize((mask_left_width, new_height))


        mask_right_img = self._mask_img.crop((width // 2, 0, width, height))
        mask_right_width = self.get_distance_from_point_to_line(chin_right_point, nose_point, chin_bottom_point)
        mask_right_width = int(mask_right_width * width_ratio)
        mask_right_img = mask_right_img.resize((mask_right_width, new_height))


        size = (mask_left_img.width + mask_right_img.width, new_height)
        mask_img = Image.new('RGBA', size)
        mask_img.paste(mask_left_img, (0, 0), mask_left_img)
        mask_img.paste(mask_right_img, (mask_left_img.width, 0), mask_right_img)

        # 计算旋转角度
        angle = np.arctan2(chin_bottom_point[1] - nose_point[1], chin_bottom_point[0] - nose_point[0])
        rotated_mask_img = mask_img.rotate(angle, expand=True)

        # 计算中心点位置
        center_x = (nose_point[0] + chin_bottom_point[0]) // 2
        center_y = (nose_point[1] + chin_bottom_point[1]) // 2

        offset = mask_img.width // 2 - mask_left_img.width
        radian = angle * np.pi / 180
        box_x = center_x + int(offset * np.cos(radian)) - rotated_mask_img.width // 2
        box_y = center_y + int(offset * np.sin(radian)) - rotated_mask_img.height // 2

        # 淹膜
        self._face_img.paste(mask_img, (box_x, box_y), mask_img)

定义距离公式-欧式距离: dist ⁡ ( X , Y ) = ∑ i = 1 n ( x i − y i ) 2 \operatorname{dist}(X, Y)=\sqrt{\sum_{i=1}^{n}\left(x_{i}-y_{i}\right)^{2}} dist(X,Y)=i=1n(xiyi)2

    @staticmethod
    def get_distance_from_point_to_line(point, line_point1, line_point2):
        distance = np.abs((line_point2[1] - line_point1[1]) * point[0] +
                          (line_point1[0] - line_point2[0]) * point[1] +
                          (line_point2[0] - line_point1[0]) * line_point1[1] +
                          (line_point1[1] - line_point2[1]) * line_point1[0]) / \
                   np.sqrt((line_point2[1] - line_point1[1]) * (line_point2[1] - line_point1[1]) +
                           (line_point1[0] - line_point2[0]) * (line_point1[0] - line_point2[0]))
        return int(distance)

测试效果如下:
在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/Peyzhang/article/details/126330891
今日推荐