Python_paddlehub篇_实现人脸图像戴口罩

目录

paddlehub的安装

利用paddlehub生成戴口罩的图片

demo总结

联系我们,一起学Python吧


paddlehub的安装

安装paddle框架

我们先创建一个虚拟环境,名字随意,我这里起的名字为paddle,python指定版本为3.6,命令如下所示。

conda create -n paddle python=3.6
  • 安装paddle之前需要先安装好cuda和cudnn了,如果大家没有安装,则需要先安装这两个加速器,然后再进入到我们的虚拟环境,开始安装paddle,paddle官网地址
#进入虚拟环境
conda activate paddle
#根据操作系统,python版本以及cuda版本安装paddle。
python -m pip install paddlepaddle-gpu==1.8.4.post107 -i https://mirror.baidu.com/pypi/simple
  • 检查paddle是否安装成功,再终端输入以下命令。
import paddle
paddle.fluid.install_check.run_check()
  • 如果出现和下图一样的信息,则说明安装成功。
  • paddle安装成功

安装paddlehub

pip install paddlehub --upgrade -i https://pypi.tuna.tsinghua.edu.cn/simple
  •  利用pip list或者pip show paddlehub,有paddlehub信息则说明安装成功,如下图所示。

    paddlehub


    paddlehub

利用paddlehub生成戴口罩的图片

利用paddlehub检测脸部关键点

  • paddlehub检测出来的人脸关键点如下所所示,每个数字代表每一个脸部具体的位置。
    脸部关键点
  • 具体图片的关键点的检测图如下所示。

    在这里插入图片描述

  • 下面的函数将口罩将要粘贴的四个关键点给返回出来。
import paddlehub as hub

def get_key_points(img):
    # 加载人脸检测模型
    face_landmark = hub.Module(name='face_landmark_localization')
    # 利用人脸关键点检测模型开始检测人脸图片,并将图片加载到work目录下
    result = face_landmark.keypoint_detection(images=[img], batch_size=1, use_gpu=False, output_dir='./work',
                                              visualization=True)
    # result[0]['data'][0]为所有检测到的关键点
    location = result[0]['data'][0]
    # 左眼睛靠下的位置就是2的位置
    left = int(location[2][0])
    # 右眼考下的位置也就是16的位置
    right = int(location[16][0])
    # 鼻梁的位置
    top = int(location[29][1])
    # 下巴的位置
    bottom = int(location[9][1])
    # 将所有的点以列表形式返回
    return [left, bottom, right, top];

将口罩图片和人脸图片结合起来

  • 如下面的代码所示。
def wear_mask(mask_img, face_img):
    '''给图像带上口罩'''
    # 把原图像复制一份给face_img_copy,不然原图是带关键点图的图片
    face_img_copy = face_img.copy();
    face_points = get_key_points(face_img)
    left = face_points[0];
    bottom = face_points[1];
    right = face_points[2];
    top = face_points[3];
    # 口罩的宽度
    resize_width = right - left;
    # 口罩的长度
    resize_height = bottom - top;
    # 调整口罩的大小
    mask_img = cv2.resize(mask_img, (resize_width, resize_height))
    # 分离通道
    mask_channels = cv2.split(mask_img)
    face_channels = cv2.split(face_img_copy)
    b, g, r, a = cv2.split(mask_img)
    # 遍历每个通道
    for c in range(0, 3):
        face_channels[c] = np.array(face_channels[c], dtype=np.uint8)
        k = np.uint8((255.0 - a) / 255)
        # 遍历原图像的每个通道让口罩区域变得透明
        face_channels[c][top:top + resize_height, left:left + resize_width] = face_channels[c][top:top + resize_height,
                                                                              left:left + resize_width] * k;
        mask_channels[c] *= np.array(a / 255, dtype=np.uint8)
        # # 因为口罩区域调整完毕之后可能有黑边,这里将像素值小于100的调整为255白色
        mask_channels[c] = remove_black_side(mask_channels[c])
        # 原图像的口罩区域逐通道加上口罩的通道像素值
        face_channels[c][top:top + resize_height, left:left + resize_width] += np.array(mask_channels[c],
                                                                                        dtype=np.uint8)
    # 通道合并为完整的图像
    result_img = cv2.merge(face_channels)
    return result_img;
  • 口罩的图片

    在这里插入图片描述

  • 输入图像进行测试的代码
# 读入的测试图像
face_img = cv2.imread('./data/cool_boy.jpg')
# 口罩图像
mask_img = cv2.imread('./data/mask666.png', -1)
# 带上口罩的图像
result_img = wear_mask(mask_img, face_img)
# 显示图像
cv2.imshow("result.img", result_img)
cv2.waitKey(0)

有黑边


这样出来之后口罩周围其实还是有黑边的,下面的函数可以将黑色的边缘像素点转换为白色。

def remove_black_side(mask_channels):
    '''因为口罩区域调整完毕之后可能有黑边,这里将像素值小于100的调整为255白色'''
    for i in range(mask_channels.shape[0]):
        for j in range(mask_channels.shape[1]):
            if mask_channels[i][j] < 100:
                mask_channels[i][j] = 255;
    return mask_channels;

  • 最后的效果图如下所示

    在这里插入图片描述

  • 总体来说效果还不错,后面位置还需要再微调以下,以及还有一些小的黑像素点也需要去除。
  • 完整代码如下所示
import cv2
import numpy as np
import paddlehub as hub

def get_key_points(img):
    # 加载人脸检测模型
    face_landmark = hub.Module(name='face_landmark_localization')
    # 利用人脸关键点检测模型开始检测人脸图片,并将图片加载到work目录下
    result = face_landmark.keypoint_detection(images=[img], batch_size=1, use_gpu=False, output_dir='./work',
                                              visualization=True)
    # result[0]['data'][0]为所有检测到的关键点
    location = result[0]['data'][0]
    # 左眼睛靠下的位置就是2的位置
    left = int(location[2][0])
    # 右眼考下的位置也就是16的位置
    right = int(location[16][0])
    # 鼻梁的位置
    top = int(location[29][1])
    # 下巴的位置
    bottom = int(location[9][1])
    # 将所有的点以列表形式返回
    return [left, bottom, right, top];

def remove_black_side(mask_channels):
    '''因为口罩区域调整完毕之后可能有黑边,这里将像素值小于100的调整为255白色'''
    for i in range(mask_channels.shape[0]):
        for j in range(mask_channels.shape[1]):
            if mask_channels[i][j] < 100:
                mask_channels[i][j] = 255;
    return mask_channels;

def wear_mask(mask_img, face_img):
    '''给图像带上口罩'''
    # 把原图像复制一份给face_img_copy,不然原图是带关键点图的图片
    face_img_copy = face_img.copy();
    face_points = get_key_points(face_img)
    left = face_points[0];
    bottom = face_points[1];
    right = face_points[2];
    top = face_points[3];
    # 口罩的宽度
    resize_width = right - left;
    # 口罩的长度
    resize_height = bottom - top;
    # 调整口罩的大小
    mask_img = cv2.resize(mask_img, (resize_width, resize_height))
    # 分离通道
    mask_channels = cv2.split(mask_img)
    face_channels = cv2.split(face_img_copy)
    b, g, r, a = cv2.split(mask_img)
    # 遍历每个通道
    for c in range(0, 3):
        face_channels[c] = np.array(face_channels[c], dtype=np.uint8)
        k = np.uint8((255.0 - a) / 255)
        # 遍历原图像的每个通道让口罩区域变得透明
        face_channels[c][top:top + resize_height, left:left + resize_width] = face_channels[c][top:top + resize_height,
                                                                              left:left + resize_width] * k;
        mask_channels[c] *= np.array(a / 255, dtype=np.uint8)
        # 因为口罩区域调整完毕之后可能有黑边,这里将像素值小于100的调整为255白色
        mask_channels[c] = remove_black_side(mask_channels[c])
        # 原图像的口罩区域逐通道加上口罩的通道像素值
        face_channels[c][top:top + resize_height, left:left + resize_width] += np.array(mask_channels[c],
                                                                                        dtype=np.uint8)
    # 通道合并为完整的图像
    result_img = cv2.merge(face_channels)
    return result_img;


# 读入的测试图像
face_img = cv2.imread('./data/baby.jpg')
# 口罩图像
mask_img = cv2.imread('./data/mask666.png', -1)
# 带上口罩的图像
result_img = wear_mask(mask_img, face_img)
# 显示图像
cv2.imshow("result.img", result_img)
cv2.waitKey(0)

demo总结

  • 使用paddlehub框架可以很方便地实现人脸的关键点检测,并且精度也挺高。当然paddlehub框架不仅仅是人脸关键点检测,还有NLP以及其他领域的一些应用,更多的介绍大家可以去官网看看。
  • 在得到关键点位置之后,我们可以根据这些关键点来做一些有意思的小demo。比如修改脸型,放大眼睛,等等…。
  • 这次实现的过程中,其实还是有一些困难的,直接把口罩的图片贴在脸部的位置,这时候是一个矩形,口罩旁边的白色也会显示出来,效果非常不好。后来又搜了搜其他的实现方式,通过逐通道叠加的方式可以处理掉这个问题,但同时口罩的边缘也会有黑色。这时候再遍历这个口罩区域,把黑色像素值转换为白色,效果上会好一点。
  • 总的来说,从这次实现中,自己也收获了很多。

 

联系我们,一起学Python吧

每周每日,分享Python实战代码,入门资料,进阶资料,基础语法,爬虫,数据分析,web网站,机器学习,深度学习等等。


​微信群(关注「Python家庭」一起轻松学Python吧)

​个人微信(备注来意,学习交流,合作,聊聊人生~)

​  

猜你喜欢

转载自blog.csdn.net/qq_34409973/article/details/108529498