python给人脸带上口罩(简单版)
导读
因为目前公开的口罩人脸
数据比较少,如果想训练一个口罩人脸识别模型,必须依赖大量的人脸数据。为了收集到更多的口罩人脸数据,我们只能利用已有的公开人脸数据上通过程序来模拟人脸带口罩
。这篇文章向大家介绍一个简单版本使用python来给正常人脸带上口罩的思路和代码
原理介绍
想要给人脸戴口罩,就必须要用到人脸关键点
的信息,通过关键点信息,我们就能知道应该将口罩放在哪个位置
- 人脸关键点检测
这里我们使用的是68个人脸关键点
,关键点的位置在人脸上的分布如下图所示
后面我们只需要用到其中四个关键点,用来计算口罩的位置,鼻梁第28点
,下巴的第2、9、16点
- 根据关键点计算口罩的size
我们需要根据上面提到的四个关键点来计算口罩的width
和height
。口罩的宽利用点2和点16的欧式距离,口罩的高用点28和点9的欧式距离
。
实际使用中,建议将口罩分为左右两部分,因为有时候头部会向左或右偏转,分成两部分计算效果会好些。口罩的高度计算不变,计算左半部分口罩的宽利用点2
到直线
(由点28和点9组成)的距离,同理可知右半部分口罩的宽计算。
- 口罩角度的调整
因为人脸可能是歪的,利用点28和点9组成的直线结合垂直线计算偏转角度
(人脸是正的,点28和点9组成的直线是垂直水平线),通过偏转角度来选择口罩
- 口罩位置的确定
利用点28和点9来确定口罩所处位置的中心点
,针对头会左右旋转的问题,需要对口罩的中心位置的确定进行微调,具体细节实现可以参考代码。
代码实现
环境准备
- python版本:3.7
- 第三方库安装
#安装OpenCV
pip install opencv-python
#安装numpy
pip install numpy
#安装PIL
pip install pillow
#安装pytorch,pytorch (>=1.0)
#建议安装cuda版本的pytorch
#安装教程:https://pytorch.org/get-started/previous-versions/
#安装人脸关键点检测face_alignment
pip install face-alignment
- 关键点模型下载不了的问题
如果在使用face-alignment
的时候无法下载模型文件,可以直接从下面的地址进行下载:
https://www.adrianbulat.com/downloads/python-fan/2DFAN-4.pth.tar
https://www.adrianbulat.com/downloads/python-fan/3DFAN-4.pth.tar
https://www.adrianbulat.com/downloads/python-fan/depth.pth.tar
将下载好的模型解压后得到pth
模型文件,对linux系统,将解压后得到的pth文件放到~/.face_alignment/data
目录下
口罩mask的提取
需要注意的是,准备的口罩mask最好是png(RGBA)透明背景
的图片。否则在将口罩mask复制到人脸上时会遮盖多余的部分,影响效果。
我这里实现了一个从纯色背景的口罩jpg图片中,提取出一个透明背景的png口罩图片,代码如下
import cv2
import numpy as npimg = cv2.imread("mask_images/mask.jpg")
#将图片分割为三个通道
b_channel,g_channel,r_channel = cv2.split(img)
alpha_channel = np.zeros(b_channel.shape,dtype=b_channel.dtype)
gray_img = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)
blur_img = cv2.GaussianBlur(gray_img,(3,3),cv2.BORDER_DEFAULT)
canny_img = cv2.Canny(blur_img,50,150)
contours,hierarchy = cv2.findContours(canny_img,cv2.RETR_EXTERNAL,cv2.CHAIN_APPROX_NONE)
#获取面积最大的轮廓
contour = max(contours,key=cv2.contourArea)
#获取最大轮廓的凸包
hull = cv2.convexHull(contour)
#初始化一个alpha通道
alpha_channel = cv2.drawContours(alpha_channel,[hull],-1,255,-1)
png_img = cv2.merge((b_channel,g_channel,r_channel,alpha_channel))
#获取最大轮廓的最小外接矩形
rect = cv2.minAreaRect(contour)
#获取矩形四个顶点的坐标
box = cv2.boxPoints(rect)
#将矩形转换为水平的矩形
x_min = int(np.min(box[:,0]))
y_min = int(np.min(box[:,1]))
x_max = int(np.max(box[:,0]))
y_max = int(np.max(box[:,1]))
png_img = png_img[y_min:y_max,x_min:x_max,:]
cv2.imwrite("mask_images/mask.png",png_img)
给人脸添加口罩
import os,face_alignment
from PIL import Image
import numpy as npclass WearFaceMask(object):def __init__(self,face_path,mask_path,save_path,enlarge_ratio=0.9,use_gpu=True,show=False):self.face_path = face_pathself.mask_path = mask_pathself.save_path = save_pathself.enlarge_ratio = enlarge_ratioself.use_gpu = use_gpuself.show = showif use_gpu:self.fa=face_alignment.FaceAlignment(face_alignment.LandmarksType._2D, device='cuda')else:self.fa = face_alignment.FaceAlignment(face_alignment.LandmarksType._2D, device='cpu')def get_key_landmarks(self,face_landmarks):"""从68个关键点中获取4个关键点的位置用来定口罩佩戴的位置:param face_landmarks:人脸68个关键点:return:"""#获取下巴右边佩戴口罩的位置(关键点2)self.left_chin_point = face_landmarks[1]#获取鼻梁佩戴口罩的位置(关键点28)self.nose_point = face_landmarks[27]#获取下巴左边佩戴口罩的位置(关键点16)self.right_chin_point = face_landmarks[15]#获取下巴最下面佩戴口罩的位置(关键点9)self.bottom_chin_point = face_landmarks[8]@staticmethoddef cal_point_to_line_dist(point,line_point1,line_point2):"""计算点到直线的距离:param point: 点的坐标:param line_point1: 直线上第一点的坐标:param line_point2: 直线上另一点的坐标:return: 点到直线的距离"""#计算点和直线上点组成的向量vec1 = line_point1 - pointvec2 = line_point2 - pointdist = abs(np.cross(vec1,vec2)) / np.linalg.norm(line_point2 - line_point1)return distdef wear_face_mask(self):self._face_img = Image.open(self.face_path)self._mask_img = Image.open(self.mask_path)face_landmarks = self.fa.get_landmarks(np.asarray(self._face_img))[0].astype(np.int32)#获取需要的关键点信息self.get_key_landmarks(face_landmarks)#获取口罩的宽和高mask_width = self._mask_img.widthmask_height = self._mask_img.height#计算口罩适应人脸后和高度new_mask_height = int(np.linalg.norm(self.bottom_chin_point - self.nose_point))#将口罩分割为左右两部分用来适配人脸#左边口罩人脸mask_left_img = self._mask_img.crop((0,0,mask_width//2,mask_height))mask_left_width = self.cal_point_to_line_dist(self.left_chin_point,self.nose_point,self.bottom_chin_point)mask_left_width = int(mask_left_width * self.enlarge_ratio)mask_left_img = mask_left_img.resize((mask_left_width,new_mask_height))#右边口罩人脸mask_right_img = self._mask_img.crop((mask_width//2,0,mask_width,mask_height))mask_right_width = self.cal_point_to_line_dist(self.right_chin_point,self.nose_point,self.bottom_chin_point)mask_right_width = int(mask_right_width * self.enlarge_ratio)mask_right_img = mask_right_img.resize((mask_right_width,new_mask_height))#合并口罩size = (mask_left_width+mask_right_width,new_mask_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_width,0),mask_right_img)#计算人脸的旋转角度angle = np.arctan2(self.bottom_chin_point[1]-self.nose_point[1],self.bottom_chin_point[0]-self.nose_point[0])#旋转口罩rotated_mask_img = mask_img.rotate(angle,expand=True)#计算mask的位置mask_center_x = (self.nose_point[0]+self.bottom_chin_point[0]) // 2mask_center_y = (self.nose_point[1]+self.bottom_chin_point[1]) // 2offset = mask_img.width // 2 - mask_left_width#将弧度转换为角度radian = angle * np.pi / 180#对口罩的位置进行微调box_x = mask_center_x + int(offset * np.cos(radian)) - rotated_mask_img.width // 2box_y = mask_center_y + int(offset * np.sin(radian)) - rotated_mask_img.height // 2self._face_img.paste(mask_img,(box_x,box_y),mask_img)self.save()def save(self):self._face_img.save(self.save_path)print(f'Save to {self.save_path}')face_path="imgs/test.jpg"
mask_path="mask_images/mask.png"
save_path="imgs/test_mask.jpg"
WearFaceMask(face_path,mask_path,save_path).wear_face_mask()
接下来我们试试给最不喜欢戴口罩的特没谱同志带上口罩,看看效果如何。感觉好像效果还是差了那么点,下篇文章介绍另一种方法来提升一下这个效果。
代码我已经上传到gitee:https://gitee.com/pragmaticAgile/wear_face_mask.git
python给人脸带上口罩(简单版)相关推荐
- python 提取最小外接矩形_python给人脸带上口罩(简单版)
导读 因为目前公开的口罩人脸数据比较少,如果想训练一个口罩人脸识别模型,必须依赖大量的人脸数据.为了收集到更多的口罩人脸数据,我们只能利用已有的公开人脸数据上通过程序来模拟人脸带口罩.这篇文章向大家介 ...
- 用Python给你的女神带上口罩~
前言 2019 年底开始蔓延的新型肺炎疫情牵动人心,作为个体,我们力所能及的就是尽量待在家中少出门. 看到一些朋友叫设计同学帮忙给自己的头像戴上口罩,作为技术人,心想一定还有更多人有这样的诉求,不如开 ...
- 给人脸戴上口罩,Python实战项目来了
大家好,人生苦短,我用Python.今天给大家分享一个Python 实战案例:为人脸照片添加口罩,喜欢本文记得收藏.点赞.关注. 废话不多说,我们先展示最终的效果. [注]完整版代码.资料,技术沟通, ...
- 使用Python为人脸自动生成口罩
来源:深度学习与计算机视觉 本文使用OpenCV dlib库生成口罩 口罩已经被证明是防止COVID-19传播的最好的防御措施之一,然而,这也导致了基于面部特征(包括鼻子.嘴和下巴线)的面部识别算法的 ...
- 这顶海贼王的帽子,我Python给你带上了 | 【人脸识别应用】
微信公众号:AI算法与图像处理 关注可了解更多的资料及技巧.问题或建议,请公众号留言; 如果你觉得对你有帮助,欢迎分享和转发哈 本文主要参考: zhuanlan.zhihu.com/p/3229975 ...
- 图像修复神器!带上口罩都能还原!DDPM:用去噪扩散概率模型极限修复图像,效果太牛了!...
点击下方卡片,关注"CVer"公众号 AI/CV重磅干货,第一时间送达 转载自:机器之心 | 编辑:杜伟.陈萍 无论掩码类型如何多变,苏黎世联邦理工学院计算机视觉实验室(CVL)的 ...
- 基于Python的人脸自动戴口罩系统
目录 1.项目背景 2.页面设计 3.器官识别 4.退出系统 1.项目背景 2019年新型冠状病毒感染的肺炎疫情发生以来,牵动人心,举国哀痛,口罩.酒精.消毒液奇货可居.
- Python打造五线图谱(乐活五线谱)简单版
效果图: 环境 python 3.7 scipy==1.1.0 plotly==4.7.1 cufflinks==0.17.3 计算代码 import pandas as pd import tali ...
- web人脸识别登陆系统简单版(springboot+mybatis)
先获取人脸识别的sdk 进入官网下载:链接: 开发者中心 获取到APPID和SDK KEY window下的配置文件 人脸识别的jar包 人脸识别的demo 最后完成的效果图 完整的项目地址 gith ...
最新文章
- 利用Jenkins的Pipeline实现集群自动化部署SpringBoot项目
- JMeter学习(六)集合点
- 如何在Chrome调试器里检查嵌套Observable对象
- 鲶鱼效应:为什么要适当的贷款?
- [Python3]Python面向对象的程序设计
- 外籍主管眼中的阿里巴巴
- JAVA面试中问及HIBERNATE与 MYBATIS的对比,在这里做一下总结(转)
- Swift 面向协议编程 基础篇 (一) 介绍
- 强制 转换string 的一个简单方法(笔记)
- 美股第三次熔断!一觉醒来,苹果损失了1.5亿部iPhone 11 Pro
- Linear Algebra - Determinant(几何意义)
- 【Computer Organization笔记07】实验课:可编程逻辑器件介绍,硬件编程方法与原则,硬件编程流程
- Quidway S1700系列企业网交换机
- VS2017超有用秘钥(亲测)
- 华为语音网关iad208e(m)华为8口语音网关web界面
- 大白菜超级U盘启动盘制作工具极速装机版
- 【课程作业】学术英语写作:文献阅读报告2
- require的用法 php,PHP 关于require()文件包含的用法详解
- 微信公众号 - Java推送小程序订阅消息给用户
- USACO-Healthy Holsteins