基于百度PaddleHub实现人像美颜V1.0

2023-11-12

AI美颜核心技术之一就是人脸关键点检测。PaddleHub已经开源了人脸关键点检测模型 face_landmark_localization。

人脸关键点检测是人脸识别和分析领域中的关键一步,它是诸如自动人脸识别、表情分析、三维人脸重建及三维动画等其它人脸相关问题的前提和突破口。

该模型支持同一张图中的多个人脸检测。它可以识别人脸中的68个关键点。
在这里插入图片描述

一、加载图片,检测关键点

import cv2
import paddlehub as hub
import matplotlib.pyplot as plt 
import matplotlib.image as mpimg
import numpy as np
import math

src_img = cv2.imread('./2.jpg')

module = hub.Module(name="face_landmark_localization")
result = module.keypoint_detection(images=[src_img])

tmp_img = src_img.copy()
for index, point in enumerate(result[0]['data'][0]):
	# print(point)
	# cv2.putText(img, str(index), (int(point[0]), int(point[1])), cv2.FONT_HERSHEY_COMPLEX, 3, (0,0,255), -1)
	cv2.circle(tmp_img, (int(point[0]), int(point[1])), 2, (0, 0, 255), -1)

res_img_path = 'face_landmark.jpg'
cv2.imwrite(res_img_path, tmp_img)

img = mpimg.imread(res_img_path) 
# 展示预测68个关键点结果
plt.figure(figsize=(10,10))
plt.imshow(img) 
plt.axis('off') 
plt.show()

在这里插入图片描述

二、实现美颜方法

  1. 瘦脸
    首先介绍如何利用识别到的68个关键点完成瘦脸功能。 利用其中3号点到5号点距离作为瘦左脸距离,13号点到15号点距离作为瘦右脸距离。同时利用局部平移算法完成瘦脸。
def thin_face(image, face_landmark):
    """
    实现自动人像瘦脸
    image: 人像图片
    face_landmark: 人脸关键点
    """
    end_point = face_landmark[30]

    # 瘦左脸,3号点到5号点的距离作为瘦脸距离
    dist_left = np.linalg.norm(face_landmark[3] - face_landmark[5])
    local_traslation_warp(image, face_landmark[3], end_point, dist_left)

    # 瘦右脸,13号点到15号点的距离作为瘦脸距离
    dist_right = np.linalg.norm(face_landmark[13] - face_landmark[15])
    image = local_traslation_warp(image, face_landmark[13], end_point, dist_right)
    return image
def local_traslation_warp(image, start_point, end_point, radius):
    """
    局部平移算法
    """
    radius_square = math.pow(radius, 2)
    image_cp = image.copy()

    dist_se = math.pow(np.linalg.norm(end_point - start_point), 2)
    height, width, channel = image.shape
    for i in range(width):
        for j in range(height):
            # 计算该点是否在形变圆的范围之内
            # 优化,第一步,直接判断是会在(start_point[0], start_point[1])的矩阵框中
            if math.fabs(i - start_point[0]) > radius and math.fabs(j - start_point[1]) > radius:
                continue

            distance = (i - start_point[0]) * (i - start_point[0]) + (j - start_point[1]) * (j - start_point[1])

            if (distance < radius_square):
                # 计算出(i,j)坐标的原坐标
                # 计算公式中右边平方号里的部分
                ratio = (radius_square - distance) / (radius_square - distance + dist_se)
                ratio = ratio * ratio

                # 映射原位置
                new_x = i - ratio * (end_point[0] - start_point[0])
                new_y = j - ratio * (end_point[1] - start_point[1])

                new_x = new_x if new_x >=0 else 0
                new_x = new_x if new_x < height-1 else height-2
                new_y = new_y if new_y >= 0 else 0
                new_y = new_y if new_y < width-1 else width-2

                # 根据双线性插值法得到new_x, new_y的值
                image_cp[j, i] = bilinear_insert(image, new_x, new_y)
                
    return image_cp

def bilinear_insert(image, new_x, new_y):
    """
    双线性插值法
    """
    w, h, c = image.shape
    if c == 3:
        x1 = int(new_x)
        x2 = x1 + 1
        y1 = int(new_y)
        y2 = y1 + 1

        part1 = image[y1, x1].astype(np.float) * (float(x2) - new_x) * (float(y2) - new_y)
        part2 = image[y1, x2].astype(np.float) * (new_x - float(x1)) * (float(y2) - new_y)
        part3 = image[y2, x1].astype(np.float) * (float(x2) - new_x) * (new_y - float(y1))
        part4 = image[y2, x2].astype(np.float) * (new_x - float(x1)) * (new_y - float(y1))

        insertValue = part1 + part2 + part3 + part4

        return insertValue.astype(np.int8)
face_landmark = np.array(result[0]['data'][0], dtype='int')

src_img = thin_face(src_img, face_landmark)

res_img_path = 'res.jpg'
cv2.imwrite(res_img_path, src_img)

img = mpimg.imread(res_img_path) 
# 展示瘦脸图片
plt.figure(figsize=(10,10))
plt.imshow(img) 
plt.axis('off') 
plt.show()

在这里插入图片描述
2. 大眼
完成瘦脸之后,我们还可以对人像中的眼睛进行放大。在识别到的左右眼中的一个位置,对其进行缩放(图像局部缩放),实现大眼。

def enlarge_eyes(image, face_landmark, radius=15, strength=10):
    """
    放大眼睛
    image: 人像图片
    face_landmark: 人脸关键点
    radius: 眼睛放大范围半径
    strength:眼睛放大程度
    """
    # 以左眼最低点和最高点之间的中点为圆心
    left_eye_top = face_landmark[37]
    left_eye_bottom = face_landmark[41]
    left_eye_center = (left_eye_top + left_eye_bottom)/2
    # 以右眼最低点和最高点之间的中点为圆心
    right_eye_top = face_landmark[43]
    right_eye_bottom = face_landmark[47]
    right_eye_center = (right_eye_top + right_eye_bottom)/2

    # 放大双眼
    local_zoom_warp(image, left_eye_center, radius=radius, strength=strength)
    local_zoom_warp(image, right_eye_center, radius=radius, strength=strength)
def local_zoom_warp(image, point, radius, strength):
    """
    图像局部缩放算法
    """
    height = image.shape[0]
    width = image.shape[1]      
    left =int(point[0] - radius) if point[0] - radius >= 0 else 0
    top = int(point[1] - radius) if point[1] - radius >= 0 else 0
    right = int(point[0] + radius) if point[0] + radius < width else width-1
    bottom = int(point[1] + radius) if point[1] + radius < height  else height-1

    radius_square = math.pow(radius, 2)
    for y in range(top, bottom):
        offset_y = y - point[1]
        for x in range(left, right):
            offset_x = x - point[0]
            dist_xy = offset_x * offset_x + offset_y * offset_y

            if dist_xy <= radius_square:
                scale = 1 - dist_xy / radius_square
                scale = 1 - strength / 100 * scale
                new_x = offset_x * scale + point[0]
                new_y = offset_y * scale + point[1]
                new_x = new_x if new_x >=0 else 0
                new_x = new_x if new_x < height-1 else height-2
                new_y = new_y if new_y >= 0 else 0
                new_y = new_y if new_y < width-1 else width-2

                image[y, x] = bilinear_insert(image, new_x, new_y)
# 在瘦脸的基础上,继续放大双眼
enlarge_eyes(src_img, face_landmark, radius=13, strength=13)

cv2.imwrite(res_img_path, src_img)

img = mpimg.imread(res_img_path) 
plt.figure(figsize=(10,10))
plt.imshow(img) 
plt.axis('off') 
plt.show()

在这里插入图片描述
3. 红唇
目前已经叠加了瘦脸、大眼的美颜功能,我们还可以给人像增添气色,给人像画上红唇。我们只需将识别到的唇部位置给涂上红色即可达到相应的目的。

def rouge(image, face_landmark, ruby=True):
    """
    自动涂口红
    image: 人像图片
    face_landmark: 人脸关键点
    ruby:是否需要深色口红
    """
    image_cp = image.copy()

    if ruby:
        rouge_color = (0,0,255)
    else:
    	rouge_color = (0,0,200)

    points=face_landmark[48:68]
    
    hull = cv2.convexHull(points)
    cv2.drawContours(image, [hull], -1, rouge_color, -1)
    cv2.addWeighted(image, 0.2, image_cp, 1-0.1, 0, image_cp)
    return image_cp
# 继续叠加红唇
src_img = rouge(src_img, face_landmark)

cv2.imwrite(res_img_path, src_img)

img = mpimg.imread(res_img_path) 
plt.figure(figsize=(10,10))
plt.imshow(img) 
plt.axis('off') 
plt.show()

在这里插入图片描述
4. 美白
人像涂上了口红吗,显得气色更佳了些。同时,很多人还会追求白皙的皮肤。最后我们还可以加上美肤功能。

def whitening(img, face_landmark):
	"""
	美白
	"""
	# 简单估计额头所在区域
	# 根据0号、16号点画出额头(以0号、16号点所在线段为直径的半圆)
	radius=(np.linalg.norm(face_landmark[0] - face_landmark[16]) / 2).astype('int32')
	center_abs=tuple(((face_landmark[0] + face_landmark[16]) / 2).astype('int32'))
	angle=np.degrees(np.arctan((lambda l:l[1]/l[0])(face_landmark[16]-face_landmark[0]))).astype('int32')
	face = np.zeros_like(img)
	cv2.ellipse(face,center_abs,(radius,radius),angle,180,360,(255,255,255),2)

	points=face_landmark[0:17]
	hull = cv2.convexHull(points)
	cv2.polylines(face, [hull], True, (255,255,255), 2)

	index = face >0
	face[index] = img[index]
	dst = np.zeros_like(face)
	# v1:磨皮程度
	v1 = 3
	# v2: 细节程度
	v2 = 2

	tmp1 = cv2.bilateralFilter(face, v1 * 5, v1 * 12.5, v1 * 12.5)
	tmp1 = cv2.subtract(tmp1,face)
	tmp1 = cv2.add(tmp1,(10,10,10,128))
	tmp1 = cv2.GaussianBlur(tmp1,(2*v2 - 1,2*v2-1),0)
	tmp1 = cv2.add(img,tmp1)
	dst = cv2.addWeighted(img, 0.1, tmp1, 0.9, 0.0)
	dst = cv2.add(dst,(10, 10, 10,255))

	index = dst>0
	img[index] = dst[index]

	return img
# 美白
src_img = whitening(src_img, face_landmark)

cv2.imwrite(res_img_path, src_img)

img = mpimg.imread(res_img_path) 
plt.figure(figsize=(10,10))
plt.imshow(img) 
plt.axis('off') 
plt.show()

在这里插入图片描述
原图:
在这里插入图片描述

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

基于百度PaddleHub实现人像美颜V1.0 的相关文章

  • python 可以检测它运行在哪个操作系统下吗?

    python 可以检测操作系统 然后为文件系统构建 if else 语句吗 我需要将 Fn 字符串中的 C CobaltRCX 替换为 FileSys 字符串 import os path csv from time import strf
  • Matplotlib 标准化颜色条 (Python)

    我正在尝试使用 matplotlib 当然还有 numpy 绘制轮廓图 它有效 它绘制了它应该绘制的内容 但不幸的是我无法设置颜色条范围 问题是我有很多图 并且需要所有图都具有相同的颜色条 相同的最小值和最大值 相同的颜色 我复制并粘贴了在
  • 为什么我不能导入 geopandas?

    我唯一的代码行是 import geopandas 它给了我错误 OSError Could not find libspatialindex c library file 以前有人遇到过这个吗 我的脚本运行得很好 直到出现此错误 请注意
  • 用 Python 编写一个无操作或虚拟类

    假设我有这样的代码 foo fooFactory create 由于种种原因 fooFactory create 可能无法创建实例Foo 如果可以的话我想要fooFactory create 返回一个虚拟 无操作对象 这个对象应该是完全惰性
  • 如何用 python 和 sympy 解决多元不等式?

    我对使用 python 和 Sympy 还很陌生 并且遇到了使用 sympy 解决多元不等式的问题 假设我的文件中有很多函数 如下所示 cst sqrt x 2 cst exp sqrt cst x 1 4 log log sqrt cst
  • 如何将条目中的部分文本加粗并更改其背景颜色?

    我正在创建一个基于 Tkinter 的 GUI 它有一个 Entry 小部件 我想将其文本的一部分加粗并更改其背景颜色 但我不知道我该怎么做 如果我使用文本小部件 我可以只使用标签 但看起来它们不能与条目小部件一起使用 此代码使用文本小部件
  • Sorted(key=lambda: ...) 背后的语法[重复]

    这个问题在这里已经有答案了 我不太明白背后的语法sorted 争论 key lambda variable variable 0 Isn t lambda随意的 为什么是variable在看起来像的内容中陈述了两次dict 我认为这里的所有
  • Python:当前目录是否自动包含在路径中?

    Python 3 4 通过阅读其他一些 SO 问题 似乎如果moduleName py文件位于当前目录之外 如果要导入它 必须将其添加到路径中sys path insert 0 path to application app folder
  • Python3 查找 2 个列表中有多少个差异才能相等

    假设我们有 2 个列表 always具有相同的长度和always包含字符串 list1 sot sot ts gg gg gg list2 gg gg gg gg gg sot 我们需要找到 其中有多少项list2应该改变 以便它等于lis
  • 当x轴不连续时如何删除冗余日期时间 pandas DatetimeIndex

    我想绘制一个 pandas 系列 其索引是无数的 DatatimeIndex 我的代码如下 import matplotlib dates as mdates index pd DatetimeIndex 2000 01 01 00 00
  • Python:随时接受用户输入

    我正在创建一个可以做很多事情的单元 其中之一是计算机器的周期 虽然我将把它转移到梯形逻辑 CoDeSys 但我首先将我的想法放入 Python 中 我将进行计数 只需一个简单的操作 counter 1 print counter 跟踪我处于
  • Python While 循环,and (&) 运算符不起作用

    我正在努力寻找最大公因数 我写了一个糟糕的 运算密集型 算法 它将较低的值减一 使用 检查它是否均匀地划分了分子和分母 如果是 则退出程序 但是 我的 while 循环没有使用 and 运算符 因此一旦分子可整除 它就会停止 即使它不是正确
  • 在wxpython中使用wx.TextCtrl并在按钮单击后显示数据的简单示例 - wx新手

    我正在学习 python 并尝试使用 wxpython 进行 UI 开发 也没有 UI exp 我已经能够创建一个带有面板 按钮和文本输入框的框架 我希望能够在文本框中输入文本 并让程序在单击按钮后对输入框中的文本执行操作 我可以获得一些关
  • Python int 太大,无法放入 SQLite

    我收到错误 OverflowError Python int 太大 无法转换为 SQLite INTEGER 来自以下代码块 该文件约25GB 因此必须分部分读取 length 6128765 Works on partitions of
  • 在pycharm中调试python代码

    这个问题类似于this https stackoverflow com questions 10240018 how to use pycharm to debug python script一 我正在尝试调试pyethapp https
  • 是否可以强制浮点数的指数或有效数匹配另一个浮点数(Python)?

    这是我前几天试图解决的一个有趣的问题 是否可以强制一个的有效数或指数float与另一个人一样float在Python中 出现这个问题是因为我试图重新调整一些数据 以便最小值和最大值与另一个数据集匹配 然而 我重新调整后的数据略有偏差 大约小
  • Scrapy 蜘蛛无法工作

    由于到目前为止没有任何效果 我开始了一个新项目 python scrapy ctl py startproject Nu 我完全按照教程操作 创建了文件夹和一个新的蜘蛛 from scrapy contrib spiders import
  • CSV 在列中查找最大值并附加新数据

    大约两个小时前 我问了一个关于从网站读取和写入数据的问题 从那时起 我花了最后两个小时试图找到一种方法来从输出的 A 列读取最大日期值 将该值与刷新的网站数据进行比较 并将任何新数据附加到 csv 文件而不覆盖旧的或创建重复项 目前 100
  • 如何在单独的文件中使用 FastAPI Depends 作为端点/路由?

    我在单独的文件中定义了一个 Websocket 端点 例如 from starlette endpoints import WebSocketEndpoint from connection service import Connectio
  • PyQt 中的线程和信号问题

    我在 PyQt 中的线程之间进行通信时遇到一些问题 我使用信号在两个线程 发送者和监听者 之间进行通信 发送者发送消息 期望被监听者接收 但是 没有收到任何消息 谁能建议可能出了什么问题 我确信这一定很简单 但我已经环顾了几个小时但没有发现

随机推荐

  • TS 对象可能为“未定义”,不能将类型“ XXXX

    前言 最近用 typeScript 也就是大家常说的 TS 写点东西 但是老是提醒这个未定义 那个可能为空 主要是 tsconfig json 中的严格模式我没关 所以今天总结一下 严格模式中 TS 中遇到 对象可能为 未定义 的具体场景
  • 资产扫描神器ARL增强改造

    拉取项目 首先从GitHub克隆到服务器上 git clone https github com ki9mu ARL plus docker 修改配置文件 因为ARL在配置文件里设置了黑名单 有时候项目为GOV或者EDU之类的时候无法进行扫
  • Java自定义实现字符串比较器-按照数字大小排序

    背景 在日常开发中 经常会遇到一些字符串排序的场景 场景一 字符串中包含的是纯数字 比较时想按照正常的数字大小进行排序 场景二 字符串中既包含数字又包含普通字符 比较时 普通字符想按照默认的字典进行排序 遇到字符串时则按照数字大小进行比较
  • Visual Stdio中使用番茄插件智能提示功能出问题。头文件也没有智能提示,甚至iostream都无法补全

    我在网上没有搜到同类型问题的解决办法 这个问题绝大部分人都不会遇到吧 不过我遇到了 问了大佬 也不知道什么原因 自己在大量乱点后 发现VA中的这个设置能解决问题 vs菜单栏的VASSIST gt Visual Assist Options
  • win7 64位 python3.4&opencv3.0配置安装教程

    一 安装Python 下载Python3 4 2 网址 https www python org downloads 注意 1 之前下载Python3 5后安装numpy出现了安装错误 尝试了各种解决办法 还是不能成功 看到网上有一条评论说
  • 粒子滤波(Particle filter)matlab实现

    粒子滤波是以贝叶斯推理和重要性采样为基本框架的 因此 想要掌握粒子滤波 对于上述两个基本内容必须有一个初步的了解 贝叶斯公式非常perfect 但是在实际问题中 由于变量维数很高 被积函数很难积分 常常会给粒子滤波带来很大的麻烦 为了克服这
  • Python 正则表达式

    最近研究Python爬虫 很多地方用到了正则表达式 但是没好好研究 每次都得现查文档 今天就专门看看Python正则表达式 本文参考了官方文档 re模块 模式 首先正则表达式的语法我就不说了 这玩意倒是不算难 用的时候现查就行了 正则表达式
  • 从0开始阿里云裸机安装java开发环境 Linux + Nginx+ MySQL+ Tomcat(lnmt)

    步骤1 更新阿里云的安装系统yum源 参考 https help aliyun com knowledge detail 5974184 html 参考 http blog csdn net endall article details 1
  • 数据库项目四总结:MySQL数据表的检索

    任务4 1 查询时选择列 1 基本查询语句 MySQL从数据表中查询数据的基本语句为SELECT语句 SELECT语句的基本格式是 SELECT lt 字段列表 gt FROM lt 表1 gt lt 表2 gt WHERE lt 表达式
  • MySQL的多表操作

    文章目录 1 多表关系 2 外键约束 2 1创建外键约束 2 2删除外键约束 3 对表联合查询 3 1交叉连接 3 2内连接 3 3外连接 4 子查询及子查询关键字 4 1 ALL关键字 4 2 ANY和SOME关键字 4 3 IN关键字
  • Python解析XML示例与解释

    使用工具包xml解析 python自带的工具 可以直接使用 使用示例如下 文章目录 简单案例 nodeType对应数字及其含义 简单案例
  • Sensor 结构——前照、背照、堆栈

    优异的工艺和技术可以使得即便不使用更新结构的CMOS 同样拥有更好的量子效率 固有热噪声 增益 满阱电荷 宽容度 灵敏度等关键型指标 在相同技术和工艺下 底大一级的确压死人 全画幅和aps c 人类的进步就是在不断发现问题 解决问题 背照式
  • redis master配置了密码进行主从同步

    1 如果master不设置密码 那么直接在slave服务器配置slaveof即可 配置如下 slaveof ip 端口 slaveof 221 224 85 186 6379 配置好我们看下redis的日志 看是否同步成功 5014 S 2
  • 生产线程池的定义与使用

    定义线程池 Slf4j Component public class PalmThreadPool public static int CORE POOL SIZE 4 private final AtomicInteger atomicI
  • C++ 中的常量,Const 关键字的用法(C++复习向p6)

    Const 常量 常量是固定的 程序执行期间不改变 又叫字面量 常量的类型 整数常量 0x23 浮点常量 1 23 布尔常量 true false 字符常量 n 字符串常量 nihao 定义常量 把字面量写成大写字母形式 是一个好习惯 方法
  • sql语句中分组取每组的最新数据

    今天敲sql的时候遇到了一个问题 业务流程是 检查记录 gt 整改通知 gt 整改回复 gt 检查组复查 如果复查不通过 则 检查组复查 gt 整改通知 gt 整改回复 gt 检查组复查 此时一条检查记录就可能对应多条整改通知去最新数据就用
  • JavaScript 将扁平的数组输出转为树形结构(需要考虑性能)

    扁平数组转为树形结构 做后台管理系统时也是经常用到的功能 面试时也是常常出现的 今天实现一下 引用两篇掘金大佬的文章 感谢大佬 一 什么是好算法 什么是坏算法 判断一个算法的好坏 一般从执行时间和占用空间来看 执行时间越短 占用的内存空间越
  • 刷脸设备引进越来越多的人喜欢靠脸消费

    刷脸支付已经成为今年比较热门的一个话题了 随便刷个新闻 微博或各大网络平台等都不免会看到有关刷脸支付的消息 感觉不了解刷脸支付就好像与这个时代脱离轨道了似的 那么今天就来给大家讲一讲刷脸支付对于消费者和商家各具有优势它比扫码支付更加安全便捷
  • gdb调试时显示数组

    可以用下面的方法来显示数组 p array len 其中p相当于print array就是数组首地址 也可以是数组名 len是想要显示的数组的长度 比如我有一个数组的定义 int a 1 2 3 4 5 那么想要显示的时候就可以写 p a
  • 基于百度PaddleHub实现人像美颜V1.0

    AI美颜核心技术之一就是人脸关键点检测 PaddleHub已经开源了人脸关键点检测模型 face landmark localization 人脸关键点检测是人脸识别和分析领域中的关键一步 它是诸如自动人脸识别 表情分析 三维人脸重建及三维