当前位置: 首页 > news >正文

OpneCV与dlib-换脸

文章目录

  • 一、环境准备
  • 二、基本原理
    • 1.人脸检测
    • 2.特征点提取
    • 3.图像变换与对齐
  • 三、基本步骤
  • 四、代码实现
    • 1.导入库
    • 2.定义面部特征点
    • 3.定义特征函数
      • (1)getFaceMask函数
      • (2)getM函数
      • (3)getKeyPoints函数
      • (4)normalColor函数
    • 4.数据预处理
    • 5.仿射变换
    • 6.生成并显示图像
  • 五、总结

使用OpenCV与dlib进行换脸是一个复杂但有趣的过程,它涉及人脸检测、特征点提取、图像变换和融合等多个步骤。以下是一个基于OpenCV和dlib实现换脸技术的概述:

一、环境准备

首先,需要安装OpenCV和dlib库。这两个库都是Python中常用的图像处理库,其中OpenCV提供了丰富的图像处理函数,而dlib则专注于机器学习和图像处理中的高级算法。

二、基本原理

OpenCV与dlib在换脸技术中的应用,主要基于计算机视觉和图像处理的相关原理。以下是对这一过程中涉及的关键知识与原理的详细解释:

1.人脸检测

  • 原理:使用预训练的模型(如dlib的正面人脸检测器)在图像中检测人脸区域。

OpenCV与dlib的作用:

  • OpenCV提供图像读取、预处理和显示等功能。
  • dlib则专注于人脸检测,提供高效且准确的人脸检测器。

2.特征点提取

  • 原理:在检测到的人脸区域内,使用特征点提取算法(如dlib的68点特征提取模型)提取关键特征点。
    这些特征点通常位于人脸的眼角、嘴角、鼻尖等显著位置,用于后续的人脸对齐和图像变换。

OpenCV与dlib的作用:

  • OpenCV提供图像处理函数,如灰度转换、边缘检测等,为特征点提取做准备。
  • dlib的68点特征提取模型能够准确地提取人脸特征点,为后续的图像变换提供基础。

3.图像变换与对齐

  • 原理:使用仿射变换或透视变换等图像变换算法,将源人脸的特征点区域变换到目标人脸的相应位置。
    仿射变换可以保持图像的直线性和平行性,适用于人脸的初步对齐。
    透视变换则能够处理更复杂的图像变换,如人脸的旋转和缩放。

OpenCV与dlib的作用:

  • OpenCV提供仿射变换和透视变换等图像变换函数。
  • dlib的特征点提取为图像变换提供了必要的输入信息。

三、基本步骤

1.加载人脸检测器和特征点预测模型

  • 使用dlib加载正面人脸检测器和68个特征点预测模型。这些模型用于检测图像中的人脸并提取关键特征点。

2.读取人脸图片

  • 使用OpenCV的imread函数读取两张要进行换脸的图片。

3.获取人脸的特征点

  • 将图像转换为灰度图,并使用dlib的人脸检测器检测人脸区域。然后,使用特征点预测模型提取人脸的68个特征点。这些特征点对应面部的特定位置,如眼睛、鼻子、嘴巴等。
    仿射变换三角形
  • 对每个三角形进行仿射变换,将其从源图像(即要移植脸部特征的图片)变换到目标图像(即脸部特征的目标图片)中的相应位置。这是实现换脸的关键步骤之一。

4.脸部轮廓掩模

  • 在仿射变换之后,使用凸包算法构建目标人脸区域的凸包,并生成一个掩模(mask)。这个掩模用于后续的无缝克隆步骤中,以确保换脸后的图像看起来更加自然。

四、代码实现

1.导入库

import cv2
import dlib
import numpy as np

cv2:OpenCV库,用于图像处理和计算机视觉任务。
dlib:一个包含机器学习算法和工具的库,这里用于面部特征点检测。
numpy:一个用于科学计算的库,提供了大量的数学函数和操作数组的工具。

2.定义面部特征点

JAM_POINTS = list(range(0, 17))
RIGHT_BROW_POINTS = list(range(17, 22))
LEFT_BROW_POINTS = list(range(22, 27))
NOSE_POINT = list(range(27, 35))
RIGHT_EYE_POINTS = list(range(36, 42))
LEFT_EYE_POINTS = list(range(42, 48))
MOUTH_POINTS = list(range(48, 61))
FACE_POINTS = list(range(17, 68))
#  关键点集
POINTS = [LEFT_BROW_POINTS + RIGHT_EYE_POINTS + LEFT_EYE_POINTS + RIGHT_BROW_POINTS + NOSE_POINT + MOUTH_POINTS]
# 处理元组,后续使用方便
POINTStuple = tuple(POINTS)

定义多个面部特征点的集合,如眉毛、眼睛、鼻子、嘴巴等。
POINTS变量包含了用于生成面部掩膜的特征点集合。

3.定义特征函数

(1)getFaceMask函数

def getFaceMask(im, keyPoints):     # 根据关键点获取掩膜im = np.zeros(im.shape[:2], dtype=np.float64)for p in POINTS:points = cv2.convexHull(keyPoints[p])   # 获取凸包cv2.fillConvexPoly(im, points, color=1)  # 填充凸包,数字在1~2之间# 单通道im构成3通道im(3,行,列),改变形状(行、列、3)适应0penCVim = np.array([im, im, im]).transpose((1, 2, 0))im = cv2.GaussianBlur(im, (33, 33), 0)return im
  • 根据给定的面部特征点生成一个面部掩膜。
  • 使用cv2.convexHull获取特征点的凸包,然后用cv2.fillConvexPoly填充凸包,生成掩膜。
  • 对掩膜进行高斯模糊处理,以减少边缘的锯齿效应。

(2)getM函数

def getM(points1, points2):points1 = points1.astype(np.float64)    # int转换为浮点数points2 = points2.astype(np.float64)c1 = np.mean(points1, axis=0)   #归一化:(数值-均值)/标准差c2 = np.mean(points2, axis=0)points1 -= c1   # 减去均值points2 -= c2s1 = np.std(points1)    # 方差计算标准差s2 = np.std(points2)points1 /= s1   # 除标准差,计算归一化结果points2 /= s2# 奇异值分解U, S, Vt = np.linalg.svd(points1.T * points2)R = (U * Vt).T  # 通过U和Vt找到Rreturn np.hstack(((s2 / s1) * R, c2.T - (s2 / s1) * R * c1.T))
  • 计算两个面部特征点集合之间的仿射变换矩阵。
  • 首先对特征点进行归一化处理,然后使用奇异值分解(SVD)找到最佳仿射变换矩阵。

(3)getKeyPoints函数

def getKeyPoints(im):   # 获取关键点rects = detector(im, 1)  # 获取人脸方框的位置shape = predictor(im, rects[0])s = np.matrix([[p.x, p.y] for p in shape.parts()])return s
  • 使用dlib的面部检测器和特征点预测器获取图像的面部特征点。

(4)normalColor函数

def normalColor(a, b):ksize = (155, 155)aGauss = cv2.GaussianBlur(a, ksize, 0)  # 对a进行高斯滤波bGauss = cv2.GaussianBlur(b, ksize, 0)weight = aGauss / bGauss    # 计算目标图像调整颜色的权重值,存在0除警告,可忽略。where_are_inf = np.isinf(weight)weight[where_are_inf] = 0return b * weight
  • 调整图像的颜色,使其与目标图像的颜色相匹配。
  • 通过计算两个图像的高斯模糊版本之间的比例来实现。

4.数据预处理

a = cv2.imread('xz.png')
b = cv2.imread('yy.png')detector = dlib.get_frontal_face_detector()
predictor = dlib.shape_predictor('shape_predictor_68_face_landmarks.dat')aKeyPoints = getKeyPoints(a)    # 获取关键点
bKetPoints = getKeyPoints(b)bOriginal = b.copy()aMask = getFaceMask(a, aKeyPoints)  # 获取掩膜
cv2.imshow('aMask', aMask)
cv2.waitKey()bMask = getFaceMask(b, bKetPoints)
cv2.imshow('bMask', bMask)
  1. 使用cv2.imread读取两张图像。
  2. 初始化dlib的面部检测器和68点特征点预测器。
  3. 对两张图像分别获取面部特征点,并生成对应的面部掩膜。

5.仿射变换

M = getM(aKeyPoints[POINTStuple], bKetPoints[POINTStuple])dsize = a.shape[:2][::-1]bMaskWarp = cv2.warpAffine(bMask, M, dsize, borderMode=cv2.BORDER_TRANSPARENT, flags=cv2.WARP_INVERSE_MAP)
cv2.imshow('bMaskWarp', bMaskWarp)
cv2.waitKey()mask = np.max([aMask, bMaskWarp], axis=0)
cv2.imshow('mask', mask)
cv2.waitKey()
  • 使用getM函数计算从图像b到图像a的仿射变换矩阵。
  • 使用cv2.warpAffine函数将图像b的面部(包括掩膜)根据仿射变换矩阵变换到图像a的坐标系中。

6.生成并显示图像

bWarp = cv2.warpAffine(b, M, dsize, borderMode=cv2.BORDER_TRANSPARENT, flags=cv2.WARP_INVERSE_MAP)
cv2.imshow('bWarp', bWarp)
cv2.waitKey()# 求b图片的仿射到图片a的颜色值,b的颜色值改为a的颜色
bbolor = normalColor(a, bWarp)
cv2.imshow('bcolor', bbolor)
cv2.waitKey()out = a * (1.0 - mask) + bbolor * mask
cv2.imshow('a', a)
cv2.imshow('b', b)
cv2.imshow('out', out/255)
cv2.waitKey()
cv2.destroyAllWindows()
  • 使用掩膜将变换后的图像b的颜色与图像a进行融合。
  • 在掩膜区域使用图像b的颜色,在非掩膜区域使用图像a的颜色。
  • 显示原始图像、变换后的图像和最终的换脸结果。

五、总结

使用OpenCV和dlib进行换脸是一个具有挑战性的任务,但它也是一个非常有趣和实用的应用。这里我们通过定义一系列特征函数,来对两张人图片进行操作,并将最后获得的结果进行融合展示,为大家展示了OpenCV与dlib库的联合使用。

我们可以通过修改高斯核函数的核大小来实现高质量的换脸效果。
注意:
核的宽度和高度都必须大于0。
核的宽度和高度都必须是奇数。


http://www.mrgr.cn/news/54939.html

相关文章:

  • gbn,sr和tcp的区别
  • 图像编辑大一统?多功能图像编辑框架Dedit:可基于图像、文本和掩码进行图像编辑。
  • Synopsys工具中命令中filter选项
  • 探索光耦:光耦——不间断电源(UPS)系统中的安全高效卫士
  • 关于k8s集群高可用性的探究
  • 数据库->库的操作
  • 搭建LeNet-5神经网络,并搭建自己的图像分类训练和测试的模板,模板通用!!!均有详细注释。
  • SOD-YOLOv8 - 增强YOLOv8以在交通场景中检测小目标
  • 线程的同步
  • 二、Linux 入门教程:开启大数据领域的神奇之旅
  • 【Linux】从多线程同步到生产者消费者模型:多线程编程实践
  • Qml-Item的Id生效范围
  • Java集合剖析2】Java集合底层常用数据结构
  • 利士策分享,财富多少,才是恰到好处?
  • 推荐一款多功能理科计算器:Math Resource Studio Pro
  • WPF入门_03路由事件
  • 数据结构(C语言):顺序表
  • WPF 回到主线程
  • Egg.js 项目的合理 ESLint 配置文件模板
  • 锁的原理以及使用
  • 《知道做到》
  • 【MySQL核心面试题】MySQL 核心 - Explain 执行计划详解!
  • 如何用AI大模型提升挖洞速度
  • upload-labs Pass-04
  • 使用 NASM 和 Windows API 创建一个简单窗口的完整实例
  • 图幅结合表DWG转DXF,使用DXF文件进行批量影像分幅