批量人脸画口罩

网上参考的修改了一下,图片放在根目录,命名叫做1.png,批量人脸画口罩
在这里插入图片描述
这个程序的目的是为了解决人脸数据集中的特征点缺失的不足

# -*- coding: utf-8 -*-
import os
import numpy as np
from PIL import Image, ImageFile

__version__ = '0.3.0'

IMAGE_DIR = os.path.join(os.path.dirname(os.path.abspath(__file__)), '')
DEFAULT_IMAGE_PATH = os.path.join(IMAGE_DIR, '1.png')

class FaceMasker:
    KEY_FACIAL_FEATURES = ('nose_bridge', 'chin')

    def __init__(self, face_path, mask_path, show=False, model='hog'):
        self.face_path = face_path
        self.mask_path = mask_path
        self.show = show
        self.model = model
        self._face_img: ImageFile = None
        self._mask_img: ImageFile = None

    def mask(self):
        import face_recognition

        face_image_np = face_recognition.load_image_file(self.face_path)
        face_locations = face_recognition.face_locations(face_image_np, model=self.model)
        face_landmarks = face_recognition.face_landmarks(face_image_np, face_locations)
        self._face_img = Image.fromarray(face_image_np)
        self._mask_img = Image.open(self.mask_path)

        found_face = False
        for face_landmark in face_landmarks:
            # check whether facial features meet requirement
            skip = False
            for facial_feature in self.KEY_FACIAL_FEATURES:
                if facial_feature not in face_landmark:
                    skip = True
                    break
            if skip:
                continue

            # mask face
            found_face = True
            self._mask_face(face_landmark)

        if found_face:
            if self.show:
                print('OK.')
                # self._face_img.show()

            # save
            self._save()
        else:
            print('Found no face.')

    def _mask_face(self, face_landmark: dict):
        nose_bridge = face_landmark['nose_bridge']
        nose_point = nose_bridge[len(nose_bridge) * 1 // 4]
        nose_v = np.array(nose_point)

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

        # split mask and resize
        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))

        # left
        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))

        # right
        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))

        # merge mask
        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)

        # rotate mask
        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)

        # calculate mask location
        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

        # add mask
        self._face_img.paste(mask_img, (box_x, box_y), mask_img)

    def _save(self):
        path_splits = os.path.splitext(self.face_path)
        new_face_path = path_splits[0]  + path_splits[1]
        new_face_path = new_face_path.replace('BLACK', 'BLACKMASK')
        self._face_img.save(new_face_path)
        print(f'Save to {new_face_path}')

    @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)


if __name__ == '__main__':
    black_folder = r"C:\Demos\face_detection1\hopenet_data\300W_LP\BLACK"
    for filename in os.listdir(black_folder):
        if filename.endswith(".jpg"):
            face_image_path = os.path.join(black_folder, filename)
            FaceMasker(face_image_path, DEFAULT_IMAGE_PATH, True, 'hog').mask()

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mfbz.cn/a/554697.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

短视频矩阵源头====技术文档交付

短视频矩阵源头技术文档交付 搭建短视频矩阵系统源码需要以下步骤: 1. 确定系统需求和功能:明确系统需要支持哪些功能,例如短视频的上传、存储、播放、分享、评论、点赞等。 2. 选择合适的编程语言和框架:根据需求选择合适的编程…

【python】描述性统计计算偏斜度和峭度

文章目录 1.编写计算偏斜度和峭度的函数。并用自己编写的函数计算课本23页的习题1.5数据的偏斜度和峭度。2.从1.5数据中随机抽取2个容量为20的样本,分别计算它们的平均数和标准差3.请绘制给定数据的频率分布直方图,计算数据的均值、标准差、偏斜度和峭度…

IDP之Backstage - 环境搭建

0. 目录 1. 前言2. 环境准备(Windows10下)2.1 安装nvm2.2 git和docker安装 3. 创建模板项目3.1 典型错误: fails on the yarn install step3.2 再次启动3.3 验证 4. 相关 1. 前言 本不想写这篇,因为看着官网文档写着挺简单的,但实…

【C语言】多字节字符、宽字符(涉及字符集和编码)

字符集、编码: 字符集:一个系统支持的所有抽象字符的集合。字符是各种文字和符号的总称,包括各国家文字、标点符号、图形符号、数字等。例如:ASCII、Unicode、GB2312、GBK、GB18030、BIG5(繁体中文) ... 编码方式:符号…

半导体厂商

引言: 学习了这么久了, 突然发现对某些陌生类型的单片机的历史、公司、不是很了解, 很多只是听说过, 本文的分享就是为了解决关于上述疑问的。 目录 C51 STM32 AVR PIC NXP(恩智浦) Infineon (英飞凌…

2024新手做电商——哪个平台开店更好做?多平台对比分析!

哈喽~我是电商月月 随着互联网的发展,线下创业越来越不好做 相对于其他创业项目来说,电商的门槛还相对低一点,所以一大批人创业的选择,就看向了电商行业 但准备开店的新手朋友纠结了:自己没有基础,选择哪…

Java面试:MySQL面试题汇总

1.说一下 MySQL 执行一条查询语句的内部执行过程? 答:MySQL 执行一条查询的流程如下: 客户端先通过连接器连接到 MySQL 服务器;连接器权限验证通过之后,先查询是否有查询缓存,如果有缓存(之前…

中海达亮相全国地灾防治成果交流会, 硬核产品引关注

4月17日-18日,全国地质灾害防治新方法新技术新设备成果交流会在云南昆明召开。本次活动主题为“提升地质灾害防治能力,服务保障高质量发展”,由中国地质灾害防治与生态修复协会举办,来自业务主管部门、行业协会及相关企业等800多名…

JS-33-jQuery02-选择器

一、单个选择器 选择器是jQuery的核心。 一个选择器写出来类似$(#dom-id)。 美元符号定义 jQuery 为什么jQuery要发明选择器?回顾一下DOM操作中我们经常使用的代码: // 按ID查找: var a document.getElementById(dom-id);// 按tag查找&am…

3d模型渲染怎么会没材质---模大狮模型网

在进行3D模型渲染时,有时会遇到材质丢失的问题,这可能会给设计师们带来一些困扰。材质是渲染的重要组成部分,它们赋予了模型真实感和视觉吸引力。然而,当模型在渲染过程中出现没有材质的情况时,可能会导致最终效果不如…

服务器数据恢复—RAID5故障导致SAP+oracle数据丢失的数据恢复案例

服务器存储数据恢复环境: 某品牌服务器存储中有一组由6块SAS硬盘组建的RAID5阵列,其中有1块硬盘作为热备盘使用。上层划分若干lun,存放Oracle数据库数据。 服务器存储故障&分析: 该RAID5阵列中一块硬盘出现故障离线&#xff0…

C++类和对象第二弹(构造,析构和拷贝构造函数)

目录 前言 1. 类的6个默认成员函数 2. 构造函数 2.1 概念 2.2 特性 3. 析构函数 3.1 概念 3.2 特性 4. 拷贝构造函数 4.1 概念 4.2 特征 总结 前言 本文主要讲解类中构造函数、析构函数和拷贝构造函数。关于这三个类中默认成员函数的知识点很多,有许多…

OSPF笔记+大实验

OSPF综合大实验---实验报告 配置IP地址 R1: [R1]int g0/0/0 [R1-GigabitEthernet0/0/0]ip add 172.16.33.1 24 [R1-GigabitEthernet0/0/0]int l0 [R1-LoopBack0]ip add 172.168.34.1 24 R2: [R2]int g0/0/0 [R2-GigabitEthernet0/0/0]ip add 172.16.33.2 24…

云服务器租用价格多少钱一年?

云服务器租用价格多少钱一年?61元一年起。现在租一个服务器多少一个月?云服务器一年费用多少钱?优惠价格低至3.8元1个月,租用云服务器收费价格表:阿里云和腾讯云2核2G3M服务器优惠价格61元一年、云服务器是99元一年&am…

秋招之路 面经

这里参考一位很厉害的前辈所分享的他的嵌入式软件工程师秋招之路,自己详细的读了一下他的经历以及他的分享的秋招面试和项目经验的总结。 我的嵌入式软件工程师秋招之路(文末送福利)_嵌入式软件工程师 刷leetcode-CSDN博客 如何在面试中介绍…

鸿蒙TypeScript学习第19天【命名空间】

1、TypeScript 命名空间 命名空间一个最明确的目的就是解决重名问题。 假设这样一种情况,当一个班上有两个名叫小明的学生时,为了明确区分它们,我们在使用名字之外,不得不使用一些额外的信息,比如他们的姓&#xff0…

15V转5V3A降压同步WT6019

15V转5V3A降压同步WT6019 WT6019则是一种高效的同步降压转换器。它可以将15V的输入电压稳定转换为5V的输出电压,并保证最大3A的电流输出。这种转换器的核心在于其内部的功率MOSFET,它能够以较低的导通电阻和快速的开关速度,实现高效率的能量…

突破界限:LangChain 引领 AI 应用构建的新时代

前言 在上一篇文章中我们对 ChatWithPDF 的方案设计进行了整体的概览,现在细化下整体流程,如下图所示: 针对上面的流程,我们思考🤔一下会面临的问题: 如何读取 PDF 中的内容?(肯定…

singleCellNet(代码开源)|单细胞层面对细胞分类进行评估,褒贬不一,有胜于无

文章目录 1.前言2.singleCellNet简介3.singleCellNet demo4.评估结果5.跨物种的评估6.小结 1.前言 书接上回,上篇分享了作者做的基于bulkRNA的细胞分类评估工具CellNet及其更新版PACNet,现在分享的是单细胞数据的细胞分类评估工具singleCellNet&#xf…

NETworkManager:功能强大的网络管理与问题排除工具

关于NETworkManager NETworkManager是一款功能强大的网络管理与问题排除工具,该工具完全开源,可以帮助广大研究人员轻松管理目标网络系统并排除网络疑难问题。 该工具使用远程桌面、PowerShell、PuTTY、TigerVNC或AWS(Systems Manager&#…
最新文章