大家好,人生苦短,我用Python。今天给大家分享一个Python 实战案例:为人脸照片添加口罩,喜欢本文记得收藏、点赞、关注

废话不多说,我们先展示最终的效果。

【注】完整版代码、资料,技术沟通,文末获取。

效果展示

数据集展示

数据集来源:使用了开源数据集FaceMask_CelebA

github地址:https://github.com/sevenHsu/FaceMask_CelebA.git

部分人脸数据集:

口罩样本数据集:

为人脸照片添加口罩代码

这部分有个库face_recognition需要安装,如果之前没有用过的小伙伴可能得费点功夫。

Face Recognition 库主要封装了dlib这一 C++ 图形库,通过 Python 语言将它封装为一个非常简单就可以实现人脸识别的 API 库,屏蔽了人脸识别的算法细节,大大降低了人脸识别功能的开发难度。

#!/usr/bin/env python
# -*- coding: utf-8 -*-
# @Author  : 2014Vee
import os
import numpy as np
from PIL import Image, ImageFile__version__ = '0.3.0'IMAGE_DIR = os.path.dirname('E:/play/FaceMask_CelebA-master/facemask_image/')
WHITE_IMAGE_PATH = os.path.join(IMAGE_DIR, 'front_14.png')
BLUE_IMAGE_PATH = os.path.join(IMAGE_DIR, 'front_14.png')
SAVE_PATH = os.path.dirname('E:/play/FaceMask_CelebA-master/save/synthesis/')
SAVE_PATH2 = os.path.dirname('E:/play/FaceMask_CelebA-master/save/masks/')class FaceMasker:KEY_FACIAL_FEATURES = ('nose_bridge', 'chin')def __init__(self, face_path, mask_path, white_mask_path, save_path, save_path2, model='hog'):self.face_path = face_pathself.mask_path = mask_pathself.save_path = save_pathself.save_path2 = save_path2self.white_mask_path = white_mask_pathself.model = modelself._face_img: ImageFile = Noneself._black_face_img = Noneself._mask_img: ImageFile = Noneself._white_mask_img = Nonedef mask(self):import face_recognitionface_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)self._white_mask_img = Image.open(self.white_mask_path)self._black_face_img = Image.new('RGB', self._face_img.size, 0)found_face = Falsefor face_landmark in face_landmarks:# check whether facial features meet requirementskip = Falsefor facial_feature in self.KEY_FACIAL_FEATURES:if facial_feature not in face_landmark:skip = Truebreakif skip:continue# mask facefound_face = Trueself._mask_face(face_landmark)if found_face:# saveself._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 resizewidth = self._mask_img.widthheight = self._mask_img.heightwidth_ratio = 1.2new_height = int(np.linalg.norm(nose_v - chin_bottom_v))# leftmask_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))# rightmask_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 masksize = (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 maskangle = 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 locationcenter_x = (nose_point[0] + chin_bottom_point[0]) // 2center_y = (nose_point[1] + chin_bottom_point[1]) // 2offset = mask_img.width // 2 - mask_left_img.widthradian = angle * np.pi / 180box_x = center_x + int(offset * np.cos(radian)) - rotated_mask_img.width // 2box_y = center_y + int(offset * np.sin(radian)) - rotated_mask_img.height // 2# add maskself._face_img.paste(mask_img, (box_x, box_y), mask_img)# split mask and resizewidth = self._white_mask_img.widthheight = self._white_mask_img.heightwidth_ratio = 1.2new_height = int(np.linalg.norm(nose_v - chin_bottom_v))# leftmask_left_img = self._white_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))# rightmask_right_img = self._white_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 masksize = (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 maskangle = 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 locationcenter_x = (nose_point[0] + chin_bottom_point[0]) // 2center_y = (nose_point[1] + chin_bottom_point[1]) // 2offset = mask_img.width // 2 - mask_left_img.widthradian = angle * np.pi / 180box_x = center_x + int(offset * np.cos(radian)) - rotated_mask_img.width // 2box_y = center_y + int(offset * np.sin(radian)) - rotated_mask_img.height // 2# add maskself._black_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 = self.save_path + '/' + os.path.basename(self.face_path) + '-with-mask' + path_splits[1]# new_face_path2 = self.save_path2 + '/' + os.path.basename(self.face_path) + '-binary' + path_splits[1]new_face_path = self.save_path + '/' + os.path.basename(self.face_path) + '-with-mask' + path_splits[1]new_face_path2 = self.save_path2 + '/'  + os.path.basename(self.face_path) + '-binary' + path_splits[1]self._face_img.save(new_face_path)self._black_face_img.save(new_face_path2)#         print(f'Save to {new_face_path}')@staticmethoddef 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)# FaceMasker("/home/aistudio/data/人脸.png", WHITE_IMAGE_PATH, True, 'hog').mask()from pathlib import Pathimages = Path("E:/play/FaceMask_CelebA-master/bbox_align_celeba").glob("*")
cnt = 0
for image in images:if cnt < 1:cnt += 1continueFaceMasker(image, BLUE_IMAGE_PATH, WHITE_IMAGE_PATH, SAVE_PATH, SAVE_PATH2, 'hog').mask()cnt += 1print(f"正在处理第{cnt}张图片,还有{99 - cnt}张图片")

掩膜生成代码

这部分其实就是对使用的口罩样本的二值化,因为后续要相关模型会用到

import os
from PIL import Image# 源目录
# MyPath = 'E:/play/FaceMask_CelebA-master/facemask_image/'
MyPath = 'E:/play/FaceMask_CelebA-master/save/masks/'
# 输出目录
OutPath = 'E:/play/FaceMask_CelebA-master/save/Binarization/'def processImage(filesoure, destsoure, name, imgtype):'''filesoure是存放待转换图片的目录destsoure是存在输出转换后图片的目录name是文件名imgtype是文件类型'''imgtype = 'bmp' if imgtype == '.bmp' else 'png'# 打开图片im = Image.open(filesoure + name)# =============================================================================#     #缩放比例#     rate =max(im.size[0]/640.0 if im.size[0] > 60 else 0, im.size[1]/1136.0 if im.size[1] > 1136 else 0)#     if rate:#         im.thumbnail((im.size[0]/rate, im.size[1]/rate))# =============================================================================img = im.convert("RGBA")pixdata = img.load()# 二值化for y in range(img.size[1]):for x in range(img.size[0]):if pixdata[x, y][0] < 90:pixdata[x, y] = (0, 0, 0, 255)for y in range(img.size[1]):for x in range(img.size[0]):if pixdata[x, y][1] < 136:pixdata[x, y] = (0, 0, 0, 255)for y in range(img.size[1]):for x in range(img.size[0]):if pixdata[x, y][2] > 0:pixdata[x, y] = (255, 255, 255, 255)img.save(destsoure + name, imgtype)def run():# 切换到源目录,遍历源目录下所有图片os.chdir(MyPath)for i in os.listdir(os.getcwd()):# 检查后缀postfix = os.path.splitext(i)[1]name = os.path.splitext(i)[0]name2 = name.split('.')if name2[1] == 'jpg-binary' or name2[1] == 'png-binary':processImage(MyPath, OutPath, i, postfix)if __name__ == '__main__':    run()

推荐文章

  • 李宏毅《机器学习》国语课程(2022)来了

  • 有人把吴恩达老师的机器学习和深度学习做成了中文版

  • 上瘾了,最近又给公司撸了一个可视化大屏(附源码)

  • 如此优雅,4款 Python 自动数据分析神器真香啊

  • 梳理半月有余,精心准备了17张知识思维导图,这次要讲清统计学

  • 年终汇总:20份可视化大屏模板,直接套用真香(文末附源码)

技术交流

欢迎转载、收藏、有所收获点赞支持一下!数据、代码可以找我获取

目前开通了技术交流群,群友已超过2000人,添加时最好的备注方式为:来源+兴趣方向,方便找到志同道合的朋友

  • 方式①、发送如下图片至微信,长按识别,后台回复:加群;
  • 方式②、添加微信号:dkl88191,备注:来自CSDN
  • 方式③、微信搜索公众号:Python学习与数据挖掘,后台回复:加群

给人脸戴上口罩,Python实战项目来了相关推荐

  1. 纯前端实现人脸检测,并给你的头像戴上口罩!

    本文来自社区投稿与征集,作者 Howard Zhang,东华大学研究生在读,中科院计算所客座学生. 本文转自:https://zhuanlan.zhihu.com/p/104070435 根据春节的起 ...

  2. python 提取最小外接矩形_python给人脸带上口罩(简单版)

    导读 因为目前公开的口罩人脸数据比较少,如果想训练一个口罩人脸识别模型,必须依赖大量的人脸数据.为了收集到更多的口罩人脸数据,我们只能利用已有的公开人脸数据上通过程序来模拟人脸带口罩.这篇文章向大家介 ...

  3. python可以写什么视觉特效_Python实现视觉特效:一行命令给头像自动戴上口罩的案例...

    Python实现视觉特效:一行命令给头像自动戴上口罩的案例 发布时间:2020-07-23 16:22:40 来源:亿速云 阅读:90 作者:清晨 小编给大家分享一下Python实现视觉特效:一行命令 ...

  4. python给人脸带上口罩(简单版)

    导读 因为目前公开的口罩人脸数据比较少,如果想训练一个口罩人脸识别模型,必须依赖大量的人脸数据.为了收集到更多的口罩人脸数据,我们只能利用已有的公开人脸数据上通过程序来模拟人脸带口罩.这篇文章向大家介 ...

  5. 一行命令自动给图片戴上口罩,硬核操作!

    作者 | Prodesire 来源 | Prodesire(ID:Prodesire) 2019 年底开始蔓延的新型肺炎疫情牵动人心,作为个体,我们力所能及的就是尽量待在家中少出门. 看到一些朋友叫设 ...

  6. 精选100个Python实战项目案例,送给零基础小白的你

    前言 随着 Python 语言的流行,越来越多的人加入到了 Python 的大家庭中.为什么这么多人学 Python ?我要喊出那句话了:"人生苦短,我用 Python!",正是因 ...

  7. python项目归纳总结-这4个Python实战项目,让你瞬间读懂Python!

    原标题:这4个Python实战项目,让你瞬间读懂Python! 来自:https://www.toutiao.com/a6593456515221291528/ Python 是一种极具可读性和通用性 ...

  8. python项目-这4个Python实战项目,让你瞬间读懂Python!

    前言 Python 是一种极具可读性和通用性的编程语言.Python 这个名字的灵感来自于英国喜剧团体 Monty Python,它的开发团队有一个重要的基础目标,就是使语言使用起来很有趣.Pytho ...

  9. python有趣的小项目-有趣的十个Python实战项目,让你瞬间爱上Python!

    前言 Python 是一种极具可读性和通用性的编程语言.Python 这个名字的灵感来自于英国喜剧团体 Monty Python,它的开发团队有一个重要的基础目标,就是使语言使用起来很有趣.Pytho ...

最新文章

  1. C++实践参考——时间类
  2. android关闭触摸声音,如何在Android中以编程方式禁用触摸时的振动和声音?
  3. python拿什么做可视化界面好-用python打造可视化爬虫监控系统,酷炫的图形化界面...
  4. 鲨鱼 抓包 oracle,ubuntu下网络抓包工具wireshark tcpdump的使用
  5. mysql数据实时同步:Canal安装部署、kafka安装、zk安装、mysql安装、Canal Server+Canal Client HA,Canal+mysql+Kafka,相关验证(学习笔记)
  6. S3C2440 SPI驱动框架
  7. 分子动力学模拟软件_功能玻璃专题——分子动力学模拟预测氧化钠含量对二元钠硅酸盐玻璃弹性模量的影响...
  8. 垂直导航菜单制作技巧一
  9. springboot整合postgresql_SpringBoot应用和PostgreSQL数据库部署到Kubernetes上的一个例子-阿里云开发者社区...
  10. C# DevExpress组件 - ChartControl图表控件
  11. TeXLive升级教程
  12. Linux命令注销电脑,Linux基本命令-注销、关机、重启
  13. 股票数据Scrapy爬虫-Python网络爬虫与信息提取-北京理工大学嵩天教授
  14. CCF CSP 201903-1 小中大(C语言100分)[序列处理]
  15. Vue基础知识总结 11:前端路由vue-router
  16. 关于Three.js 加载地面贴图的坑
  17. 快速实现安卓输入法!
  18. Linux下配置JSHOP2环境
  19. matlab 边缘检测 抠图,ps如何调整边缘的流程:边缘检测、调整边缘、输出(调整边缘抠图...
  20. 【酸甜苦辣】记迭代一的酸甜苦辣(妍喆篇)

热门文章

  1. 谷歌施密特:中国人相当出色2025年将超美国成AI主导丨业界大佬财报频出【软件网每日新闻播报│第11-3期】
  2. Android adb shell后面可用的常用命令详细列举
  3. Android5.1 -Recents分析
  4. ubuntu18.04中基于Docker搭建tensorflow-gpu开发环境
  5. Cantor 表 {C语言解法}
  6. 统计学--从对P值的理解谈起
  7. linux 查询系统io,Linux系统IO实时监控iostat命令详解
  8. 使用poi替换ppt文件内的变量参数,包含ppt和pptx格式
  9. Chrome的启动参数
  10. linux钉钉-使用playonlinux 可以使用视频会议