A realistic approach to generate masked faces applied on two novel masked face recognition data sets
1 人脸添加口罩masked_faces
1、论文和代码
paper:https://arxiv.org/pdf/2109.01745v5.pdf
code:https://github.com/securifai/masked_faces
2、作者在CelebA
和 CASIA-WebFace
两个口罩数据集上添加口罩,处理出两个数据集,数据集下载地址:
- 在
CASIA-WebFace 数据集
上生成445446张(90%)
添加口罩人的人脸图片 - 在
CelebA数据集
上生成196254张 (96.8%)
张添加口罩的人脸图片
2 添加口罩原理
该实现时依赖于facebook的Spark AR Studio
,这是用于Instagram人脸滤镜的(face filter)。 作者使用该方法:
1、首先给一张原始图片
2、随机选择一个mask,然后使用SparkAR的3D face 模型进行转换mask模板
3、调整mask颜色,然后添加到人脸上
效果:
3 添加口罩代码操作
依赖python库包(tqdm、opencv-python)
1、数据准备:
- 口罩mask的模板图片
- 原始的
CelebA
和CASIA-WebFace
数据集
2、在CelebA数据集上处理过程
数据集准备:
main directory
│ apply_masks_celeba.py
└───celeba_masks - masks folder (from this repo)
│ │ ...
└───celeba - data set folder (original images)
│ │ ...
└───masked_celeba - output folder (images with overlaid masks)
│ ...
python python apply_masks_celeba.py
3、在CASIA-WebFace数据集上处理过程
数据集准备:
main directory
│ apply_masks_casia.py
└───casia_masks - masks folder (from this repo)
│ │ ...
└───casia - data set folder (original images)
│ │ ...
└───masked_casia - output folder (images with overlaid masks)
│ ...
python apply_masks_casia.py
4 源码分析
apply_masks_casia.py
# This script applies masks over Casia-WebFace dataset. casia_folder, masks_folder, output folder should be set
# SecurifAI - 2021
import os
import glob
import cv2
from tqdm import tqdm
def overlay_image_alpha(img, img_overlay, pos, alpha_mask):
x, y = pos
y1, y2 = max(0, y), min(img.shape[0], y + img_overlay.shape[0])
x1, x2 = max(0, x), min(img.shape[1], x + img_overlay.shape[1])
y1o, y2o = max(0, -y), min(img_overlay.shape[0], img.shape[0] - y)
x1o, x2o = max(0, -x), min(img_overlay.shape[1], img.shape[1] - x)
if y1 >= y2 or x1 >= x2 or y1o >= y2o or x1o >= x2o:
return
channels = img.shape[2]
alpha = alpha_mask[y1o:y2o, x1o:x2o]
alpha_inv = 1.0 - alpha
for c in range(channels):
img[y1:y2, x1:x2, c] = (alpha * img_overlay[y1o:y2o, x1o:x2o, c] +
alpha_inv * img[y1:y2, x1:x2, c])
# casia images main folder
casia_folder = 'CASIA-WebFace'
# masks main folder
masks_folder = 'CASIA-WebFace_masks'
# masks img list
mask_list = glob.glob(masks_folder + '/*/*.png')
# output folder
output_folder = 'masked_CASIA-WebFace'
if not os.path.isdir(output_folder):
os.mkdir(output_folder)
for mask in tqdm(mask_list):
# get the basename of the mask to find original Casia image
mask_basename = os.path.basename(mask)
parent_folder = os.path.basename(os.path.dirname(mask))
if not os.path.isdir(os.path.join(output_folder,parent_folder)):
os.mkdir(os.path.join(output_folder,parent_folder))
# create path for original mask
img_path = os.path.join(casia_folder, parent_folder, mask_basename.replace('png','jpg'))
# check that original image exists, if it exists load it
if os.path.isfile(img_path):
casia_image = cv2.imread(img_path)
else:
continue
# load the mask
mask_image = cv2.imread(mask,cv2.IMREAD_UNCHANGED)
# apply mask over image
overlay_image_alpha(casia_image,
mask_image[:, :, 0:3],
(0, 0),
mask_image[:, :, 3] / 255.0)
# save new overlayed image
cv2.imwrite(os.path.join(output_folder,parent_folder, mask_basename.replace('png','jpg')),casia_image)
apply_masks_celeba.py
# This script applies the celeba_masks over the celeba_images. celeba_folder, output_folder must be set.
# SecurifAI - 2021
import glob
import cv2
import os
from tqdm import tqdm
def overlay_image_alpha(img, img_overlay, pos, alpha_mask):
x, y = pos
y1, y2 = max(0, y), min(img.shape[0], y + img_overlay.shape[0])
x1, x2 = max(0, x), min(img.shape[1], x + img_overlay.shape[1])
y1o, y2o = max(0, -y), min(img_overlay.shape[0], img.shape[0] - y)
x1o, x2o = max(0, -x), min(img_overlay.shape[1], img.shape[1] - x)
if y1 >= y2 or x1 >= x2 or y1o >= y2o or x1o >= x2o:
return
channels = img.shape[2]
alpha = alpha_mask[y1o:y2o, x1o:x2o]
alpha_inv = 1.0 - alpha
for c in range(channels):
img[y1:y2, x1:x2, c] = (alpha * img_overlay[y1o:y2o, x1o:x2o, c] +
alpha_inv * img[y1:y2, x1:x2, c])
# folder where celeba images are stored
celeba_folder = 'img_celeba'
img_list = glob.glob(celeba_folder + '/*.png')
# folder where the masks are stored
mask_folder = 'celeba_masks'
mask_list = glob.glob(mask_folder + '/*.png')
# output folder
output_folder = 'masked_celeba'
if not os.path.exists(output_folder):
os.makedirs(output_folder)
for mask in tqdm(mask_list):
# get basename and remove '_mask' string, change png to jpg
mask_basename = os.path.basename(mask).replace('_mask','').replace('png','jpg')
# get celeba path from mask path
img_path = celeba_folder + '/' + mask_basename
# check if we have an image for mask
if os.path.exists(img_path):
generated_mask = cv2.imread(mask,cv2.IMREAD_UNCHANGED)
celeba_img = cv2.imread(img_path)
# apply mask over celeba_image
overlay_image_alpha(celeba_img,
generated_mask[:, :, 0:3],
(0, 0),
generated_mask[:, :, 3] / 255.0)
# write new image in output_folder
cv2.imwrite(output_folder + '/' + mask_basename, celeba_img)
这个代码不全,在readme也没有说明,开源的代码几乎是没有什么价值!