基于dlib和OpenCV的人脸替换技术详解

目录

一、换脸技术概述

[1.1 换脸技术的发展](#1.1 换脸技术的发展)

[1.2 常用换脸方法分类](#1.2 常用换脸方法分类)

[1.3 各方法优缺点对比](#1.3 各方法优缺点对比)

二、本文方法介绍

[2.1 技术路线](#2.1 技术路线)

[2.2 核心优势](#2.2 核心优势)

[2.3 工作流程图](#2.3 工作流程图)

三、代码实现详解

[3.1 环境准备](#3.1 环境准备)

[3.2 人脸关键点定义](#3.2 人脸关键点定义)

[3.3 关键点提取函数](#3.3 关键点提取函数)

[3.4 人脸掩膜生成](#3.4 人脸掩膜生成)

[3.5 仿射变换矩阵计算](#3.5 仿射变换矩阵计算)

[3.6 颜色匹配函数](#3.6 颜色匹配函数)

[3.7 完整换脸流程](#3.7 完整换脸流程)

四、效果展示与分析

[4.1 中间过程可视化](#4.1 中间过程可视化)

​编辑

[4.2 最终换脸效果](#4.2 最终换脸效果)

成功案例

案例2:不同角度

[4.3 存在的问题](#4.3 存在的问题)

[4.4 参数调优指南](#4.4 参数调优指南)

五、进阶改进方向

[5.1 短期优化(1-2天可完成)](#5.1 短期优化(1-2天可完成))

[5.2 中期改进(1周可完成)](#5.2 中期改进(1周可完成))

[5.3 长期方向(研究级)](#5.3 长期方向(研究级))

六、总结与展望

[6.1 方法总结](#6.1 方法总结)

[6.2 与深度学习方法对比](#6.2 与深度学习方法对比)

[6.3 实际应用建议](#6.3 实际应用建议)

[6.4 未来展望](#6.4 未来展望)

七、完整代码


一、换脸技术概述

1.1 换脸技术的发展

人脸替换(Face Swap)技术是计算机视觉领域的热门应用之一,近年来随着深度学习的发展,换脸技术已经从实验室走向了大众应用。从早期的Snapchat滤镜到现在的DeepFake技术,换脸技术经历了从简单到复杂、从粗糙到精细的发展过程。

1.2 常用换脸方法分类

目前主流的换脸技术主要分为以下几类:

传统计算机视觉方法:

  • 基于关键点的仿射变换:通过检测人脸关键点,计算仿射变换矩阵,将源人脸映射到目标图像上
  • 泊松融合(Poisson Blending):利用泊松方程实现无缝图像融合
  • 三角剖分方法:基于Delaunay三角剖分进行人脸区域映射

深度学习方法:

  • 基于GAN的换脸:如DeepFake、FaceSwap等,通过生成对抗网络实现高质量换脸
  • 基于自编码器的方法:通过编码器-解码器架构学习人脸特征表示
  • 3D人脸重建方法:先重建3D人脸模型,再进行纹理映射

1.3 各方法优缺点对比

方法类型 优点 缺点 适用场景
关键点仿射变换 实现简单,速度快,无需训练 效果一般,对光照敏感 实时应用、教学演示
泊松融合 边界自然,颜色过渡好 计算量较大 照片处理
深度学习方法 效果逼真,鲁棒性强 需要大量数据训练,计算资源要求高 专业制作

二、本文方法介绍

本文采用基于dlib关键点检测和OpenCV图像处理的传统换脸方法,该方法具有以下特点:

2.1 技术路线

  1. 人脸关键点检测:使用dlib预训练的68点人脸关键点检测器
  2. 仿射变换:通过Procrustes分析计算最优仿射变换矩阵
  3. 颜色匹配:使用高斯模糊实现局部颜色统一
  4. Alpha混合:通过掩膜实现平滑融合

2.2 核心优势

无需训练 :直接使用预训练模型,开箱即用

实现简单 :代码量少,易于理解和修改

处理快速 :单张图片处理仅需1-2秒

可控性强:每个步骤都可独立调整参数

2.3 工作流程图

复制代码
输入图像A(目标) + 输入图像B(源)
        ↓
   人脸关键点检测
        ↓
   计算仿射变换矩阵M
        ↓
   将B脸仿射变换到A的位置
        ↓
   生成人脸掩膜
        ↓
   颜色匹配和归一化
        ↓
   Alpha混合融合
        ↓
   输出换脸结果

三、代码实现详解

3.1 环境准备

复制代码
import cv2
import dlib
import numpy as np

所需库说明:

  • opencv-python:图像处理核心库
  • dlib:人脸检测和关键点定位
  • numpy:数值计算

下载预训练模型: 需要下载dlib的68点人脸关键点检测模型:

复制代码
wget http://dlib.net/files/shape_predictor_68_face_landmarks.dat.bz2
bunzip2 shape_predictor_68_face_landmarks.dat.bz2

3.2 人脸关键点定义

复制代码
JAW_POINTS = list(range(0, 17))        # 下巴轮廓
RIGHT_BROW_POINTS = list(range(17, 22))  # 右眉毛
LEFT_BROW_POINTS = list(range(22, 27))   # 左眉毛
NOSE_POINTS = 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_POINTS + MOUTH_POINTS]
POINTStuple = tuple(POINTS)

关键点分布说明:

dlib的68点人脸关键点按照固定顺序排列:

  • 点0-16:下巴轮廓(从左到右)
  • 点17-21:右眉毛
  • 点22-26:左眉毛
  • 点27-35:鼻子
  • 点36-41:右眼
  • 点42-47:左眼
  • 点48-60:外嘴唇轮廓
  • 点61-67:内嘴唇轮廓

3.3 关键点提取函数

复制代码
def getKeyPoints(im):
    """获取人脸68个关键点坐标"""
    rects = detector(im, 1)  # 检测人脸矩形框,1表示上采样1次
    shape = predictor(im, rects[0])  # 获取第一个人脸的关键点
    s = np.matrix([[p.x, p.y] for p in shape.parts()])
    return s

函数解析:

  1. detector(im, 1):使用HOG+SVM人脸检测器,参数1表示对图像上采样1次以检测更小的人脸
  2. predictor(im, rects[0]):对检测到的第一个人脸进行68点关键点定位
  3. 返回68×2的矩阵,每行是一个关键点的(x,y)坐标

3.4 人脸掩膜生成

复制代码
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)  # 填充凸包区域
    
    # 将单通道掩膜扩展为三通道
    im = np.array([im, im, im]).transpose((1, 2, 0))
    
    # 高斯模糊使边界柔和
    im = cv2.GaussianBlur(im, ksize=(25, 25), sigmaX=0)
    
    return im

核心思想:

  1. 凸包算法cv2.convexHull()找到包围所有关键点的最小凸多边形
  2. 掩膜填充:使用值1填充凸包区域,背景为0
  3. 高斯模糊 :关键参数!模糊半径决定了边界过渡的柔和程度
    • ksize=(25,25):25×25的模糊核
    • 值越大,边界越柔和,但可能丢失细节
    • 值越小,边界越锐利,但融合不自然

可视化理解:

复制代码
原始掩膜:        模糊后掩膜:
■■■■■■           ░░▒▒▓▓██▓▓▒▒░░
■■■■■■     →     ░▒▓███████▓▒░
■■■■■■           ░░▒▒▓▓██▓▓▒▒░░

3.5 仿射变换矩阵计算

复制代码
def getM(points1, points2):
    """使用Procrustes分析计算仿射变换矩阵"""
    points1 = points1.astype(np.float64)
    points2 = points2.astype(np.float64)

    # 计算质心
    c1 = np.mean(points1, axis=0)
    c2 = np.mean(points2, axis=0)
    
    # 去中心化
    points1 -= c1
    points2 -= c2
    
    # 计算标准差(尺度归一化)
    s1 = np.std(points1)
    s2 = np.std(points2)
    points1 /= s1
    points2 /= s2

    # 奇异值分解求解旋转矩阵
    U, S, Vt = np.linalg.svd(points1.T * points2)
    R = (U * Vt).T
    
    # 组合为仿射变换矩阵
    return np.hstack(((s2/s1)*R, c2.T-(s2/s1)*R*c1.T))

数学原理:Procrustes分析

这是一种用于比较两组点集形状的统计方法:

  1. 平移对齐:将两组点的质心都移到原点

    复制代码
    points' = points - mean(points)
  2. 尺度归一化:消除大小差异

    复制代码
    points'' = points' / std(points')
  3. 旋转对齐:通过SVD分解求解最优旋转矩阵

    复制代码
    U, S, Vt = SVD(points1.T × points2)
    R = (U × Vt).T
  4. 构建仿射矩阵

    复制代码
    M = [s2/s1 * R | t]
    其中 t = c2 - (s2/s1) * R * c1

仿射变换的作用:

  • 平移:改变人脸位置
  • 旋转:调整人脸角度
  • 缩放:匹配人脸大小
  • 不包括透视变换(无法处理3D角度差异)

3.6 颜色匹配函数

复制代码
def normalColor(a, b):
    """调整b的颜色使其与a相匹配"""
    ksize = (11, 11)
    
    # 对两张图像分别进行高斯模糊
    aGauss = cv2.GaussianBlur(a, ksize, sigmaX=0)
    bGauss = cv2.GaussianBlur(b, ksize, sigmaX=0)
    
    # 计算颜色调整权重
    weight = aGauss / bGauss
    
    # 处理无穷值(除零情况)
    where_are_inf = np.isinf(weight)
    weight[where_are_inf] = 0
    
    return b * weight

颜色匹配原理:

假设图像A和B在某个区域的平均颜色分别为C_aC_b,那么:

复制代码
调整后的B = B × (C_a / C_b)

但直接使用原图颜色会导致噪声放大,因此:

  1. 先模糊:提取局部平均颜色
  2. 计算权重weight = blur(A) / blur(B)
  3. 应用权重result = B × weight

效果对比:

复制代码
原始B脸:偏黄、光照暗
        ↓ 颜色匹配
调整后B脸:肤色接近A、亮度匹配

3.7 完整换脸流程

复制代码
# 初始化检测器
detector = dlib.get_frontal_face_detector()
predictor = dlib.shape_predictor("shape_predictor_68_face_landmarks.dat")

# 读取图像
a = cv2.imread("img_19.png")  # 目标图(背景图)
b = cv2.imread("img_16.png")  # 源图(要换的脸)
b = cv2.flip(b, 1)  # 水平翻转(如需要)

# Step 1: 获取关键点
aKeyPoints = getKeyPoints(a)
bKeyPoints = getKeyPoints(b)

# Step 2: 生成人脸掩膜
aMask = getFaceMask(a, aKeyPoints)
bMask = getFaceMask(b, bKeyPoints)

# Step 3: 计算仿射变换矩阵
M = getM(aKeyPoints[POINTStuple], bKeyPoints[POINTStuple])

# Step 4: 仿射变换B的掩膜
dsize = a.shape[:2][::-1]
bMaskWarp = cv2.warpAffine(bMask, M, dsize,
                           borderMode=cv2.BORDER_TRANSPARENT,
                           flags=cv2.WARP_INVERSE_MAP)

# Step 5: 合并掩膜
mask = np.max([aMask, bMaskWarp], axis=0)

# Step 6: 仿射变换B的人脸
bWrap = cv2.warpAffine(b, M, dsize,
                       borderMode=cv2.BORDER_TRANSPARENT,
                       flags=cv2.WARP_INVERSE_MAP)

# Step 7: 颜色匹配
bcolor = normalColor(a, bWrap)

# Step 8: Alpha混合
out = a * (1.0 - mask) + bcolor * mask

# 显示结果
cv2.imshow("out", out/255)
cv2.waitKey()

流程图示:

复制代码
图A(目标)          图B(源)
   |                 |
   v                 v
提取关键点        提取关键点
   |                 |
   +--------+--------+
            |
            v
     计算变换矩阵M
            |
      +-----+-----+
      |           |
      v           v
  生成掩膜A   仿射变换B
      |           |
      |           v
      |      颜色匹配B'
      |           |
      +-----+-----+
            |
            v
       Alpha混合
            |
            v
         结果图

四、效果展示与分析

4.1 中间过程可视化

4.2 最终换脸效果

成功案例

案例1:正面换脸

复制代码
原图A              原图B              结果
[女性正面]  +  [男性正面]  →  [男性脸+女性背景]

✅ 优点:

  • 五官位置准确对齐
  • 边界融合自然
  • 整体协调性好

⚠️ 不足:

  • 鼻梁和眼部有轻微色差
  • 光照匹配不够完美
案例2:不同角度

案例2a:侧脸换正脸

复制代码
结果质量:★★☆☆☆
问题:仿射变换无法处理3D角度差异

案例2b:正脸换正脸

复制代码
结果质量:★★★★☆
效果:较好,仅有细微色差

4.3 存在的问题

根据实际测试,该方法存在以下局限:

1. 色彩不均匀

  • 原因:简单的颜色权重无法处理复杂光照

  • 表现:眼部、鼻梁等区域出现异色或发白

  • 解决方案:

    复制代码
    # 方案1:使用LAB色彩空间a_lab = cv2.cvtColor(a, cv2.COLOR_BGR2LAB)b_lab = cv2.cvtColor(b, cv2.COLOR_BGR2LAB)# 只调整亮度通道# 方案2:直方图匹配for i in range(3):    b[:,:,i] = cv2.equalizeHist(b[:,:,i])

2. 边界不够自然

  • 原因:ksize=(25,25)的高斯模糊不够大

  • 表现:脸部边缘有明显分界线

  • 解决方案:

    复制代码
    # 增大模糊核im = cv2.GaussianBlur(im, ksize=(61, 61), sigmaX=15)# 或使用泊松融合center = (mask_center_x, mask_center_y)out = cv2.seamlessClone(bcolor, a, mask, center, cv2.NORMAL_CLONE)

3. 无法处理角度差异

  • 原因:仿射变换是2D变换,无法处理3D旋转
  • 表现:侧脸换正脸会严重扭曲
  • 解决方案:
    • 使用3D人脸重建
    • 或限制只处理正面人脸

4. 对光照敏感

  • 原因:没有光照归一化步骤

  • 表现:强光下效果差

  • 解决方案:

    复制代码
    # 添加光照归一化a_gray = cv2.cvtColor(a, cv2.COLOR_BGR2GRAY)a_norm = cv2.equalizeHist(a_gray)

4.4 参数调优指南

参数 默认值 调优建议 效果
掩膜模糊核 (25,25) 增大到(51,51)或(61,61) 边界更柔和
颜色匹配核 (11,11) 增大到(21,21) 颜色更均匀
sigmaX 0(自动) 设为10-15 更平滑的模糊
关键点数量 部分点 使用全部68点 更准确的对齐

调参示例代码:

复制代码
# 柔和边界版本
def getFaceMask_soft(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)
    im = np.array([im, im, im]).transpose((1, 2, 0))
    im = cv2.GaussianBlur(im, ksize=(61, 61), sigmaX=15)  # 更大的核
    return im

# 增强颜色匹配版本
def normalColor_enhanced(a, b):
    ksize = (21, 21)  # 更大的核
    # ... 其余代码相同

五、进阶改进方向

5.1 短期优化(1-2天可完成)

1. 添加泊松融合

复制代码
def poisson_blend(dst, src, mask):
    center = (dst.shape[1]//2, dst.shape[0]//2)
    mask_uint8 = (mask * 255).astype(np.uint8)
    return cv2.seamlessClone(src, dst, mask_uint8[:,:,0], 
                            center, cv2.NORMAL_CLONE)

2. LAB色彩空间颜色匹配

复制代码
def normalColor_lab(a, b):
    a_lab = cv2.cvtColor(a, cv2.COLOR_BGR2LAB)
    b_lab = cv2.cvtColor(b, cv2.COLOR_BGR2LAB)
    
    # 只调整L通道(亮度)
    l_mean_a = np.mean(a_lab[:,:,0])
    l_mean_b = np.mean(b_lab[:,:,0])
    b_lab[:,:,0] = b_lab[:,:,0] * (l_mean_a / l_mean_b)
    
    return cv2.cvtColor(b_lab, cv2.COLOR_LAB2BGR)

3. 直方图匹配

复制代码
def histogram_matching(src, dst):
    matched = np.zeros_like(src)
    for i in range(3):
        # 计算累积分布函数
        src_hist, bins = np.histogram(src[:,:,i], 256, [0,256])
        dst_hist, _ = np.histogram(dst[:,:,i], 256, [0,256])
        
        src_cdf = src_hist.cumsum()
        dst_cdf = dst_hist.cumsum()
        
        # 归一化
        src_cdf = src_cdf / src_cdf[-1]
        dst_cdf = dst_cdf / dst_cdf[-1]
        
        # 建立映射
        mapping = np.zeros(256, dtype=np.uint8)
        for j in range(256):
            diff = np.abs(dst_cdf - src_cdf[j])
            mapping[j] = np.argmin(diff)
        
        matched[:,:,i] = mapping[src[:,:,i]]
    
    return matched

5.2 中期改进(1周可完成)

1. 多尺度融合(拉普拉斯金字塔)

复制代码
def laplacian_blend(A, B, mask, levels=6):
    # 构建高斯金字塔
    gpA = [A]
    gpB = [B]
    gpM = [mask]
    
    for i in range(levels):
        gpA.append(cv2.pyrDown(gpA[i]))
        gpB.append(cv2.pyrDown(gpB[i]))
        gpM.append(cv2.pyrDown(gpM[i]))
    
    # 构建拉普拉斯金字塔
    lpA = [gpA[levels-1]]
    lpB = [gpB[levels-1]]
    
    for i in range(levels-1, 0, -1):
        size = (gpA[i-1].shape[1], gpA[i-1].shape[0])
        LA = gpA[i-1] - cv2.pyrUp(gpA[i], dstsize=size)
        LB = gpB[i-1] - cv2.pyrUp(gpB[i], dstsize=size)
        lpA.append(LA)
        lpB.append(LB)
    
    # 在每一层进行混合
    LS = []
    for la, lb, gm in zip(lpA, lpB, reversed(gpM)):
        ls = la * (1 - gm) + lb * gm
        LS.append(ls)
    
    # 重建图像
    result = LS[0]
    for i in range(1, levels):
        size = (LS[i].shape[1], LS[i].shape[0])
        result = cv2.pyrUp(result, dstsize=size) + LS[i]
    
    return result

2. 光照归一化

复制代码
def illumination_normalization(img):
    # 转换到YCrCb色彩空间
    ycrcb = cv2.cvtColor(img, cv2.COLOR_BGR2YCrCb)
    
    # 对Y通道进行直方图均衡化
    ycrcb[:,:,0] = cv2.equalizeHist(ycrcb[:,:,0])
    
    # 转回BGR
    return cv2.cvtColor(ycrcb, cv2.COLOR_YCrCb2BGR)

5.3 长期方向(研究级)

1. 引入深度学习

  • 使用GAN进行超分辨率重建
  • 使用神经网络进行肤色迁移
  • 使用深度模型估计3D人脸姿态

2. 3D人脸重建

  • 使用3DMM(3D Morphable Model)
  • 重建人脸的3D几何和纹理
  • 支持任意角度换脸

3. 实时视频换脸

  • 优化算法性能
  • 使用光流法实现帧间平滑
  • GPU加速

六、总结与展望

6.1 方法总结

本文介绍的基于dlib和OpenCV的换脸方法具有以下特点:

优势: ✅ 实现简单,代码量少(约150行)

✅ 无需训练,开箱即用

✅ 处理速度快(单张图片1-2秒)

✅ 易于理解和修改

✅ 适合教学和快速原型开发

劣势: ❌ 效果受限于传统CV方法

❌ 对光照和角度敏感

❌ 颜色匹配不够完美

❌ 无法处理大角度差异

❌ 边界融合仍有改进空间

适用场景:

  • 计算机视觉教学演示
  • 快速原型验证
  • 对实时性要求高的应用
  • 资源受限的嵌入式设备

6.2 与深度学习方法对比

维度 传统方法(本文) 深度学习方法
训练需求 无需训练 需要大量数据和GPU
实现难度 简单(150行代码) 复杂(数千行+模型)
处理速度 快(1-2秒/张) 慢(5-10秒/张)
效果质量 中等 优秀
鲁棒性 一般 很强
可解释性

6.3 实际应用建议

如果你需要:

  • 快速demo:用本文方法 ✅
  • 教学演示:用本文方法 ✅
  • 生产级应用:用深度学习方法(如FaceSwap、DeepFaceLab)
  • 实时视频:结合本文方法+优化(GPU加速)
  • 高质量照片:深度学习方法 + 人工精修

6.4 未来展望

换脸技术的发展方向:

  1. 更高质量:GAN生成的换脸效果将越来越逼真
  2. 更快速度:实时4K视频换脸成为可能
  3. 更低门槛:无需专业知识,手机APP即可完成
  4. 更强鲁棒性:适应各种光照、角度、遮挡情况
  5. 伦理规范:技术发展伴随着使用规范的建立

伦理提醒: ⚠️ 换脸技术虽然有趣,但使用时需注意:

  • 不得用于制作虚假信息
  • 不得侵犯他人肖像权
  • 不得用于非法或不道德用途
  • 建议在生成内容上加水印标识

七、完整代码

复制代码
"""
基于dlib和OpenCV的人脸替换实现
作者:[Your Name]
日期:2024
功能:将图片B的人脸替换到图片A上
"""

import cv2
import dlib
import numpy as np

# ==================== 人脸关键点定义 ====================
JAW_POINTS = list(range(0, 17))
RIGHT_BROW_POINTS = list(range(17, 22))
LEFT_BROW_POINTS = list(range(22, 27))
NOSE_POINTS = 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_POINTS + MOUTH_POINTS]
POINTStuple = tuple(POINTS)

# ==================== 核心函数 ====================

def getKeyPoints(im):
    """提取人脸68个关键点"""
    rects = detector(im, 1)
    shape = predictor(im, rects[0])
    s = np.matrix([[p.x, p.y] for p in shape.parts()])
    return s

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)
    
    im = np.array([im, im, im]).transpose((1, 2, 0))
    im = cv2.GaussianBlur(im, ksize=(25, 25), sigmaX=0)
    return im

def getM(points1, points2):
    """计算仿射变换矩阵"""
    points1 = points1.astype(np.float64)
    points2 = points2.astype(np.float64)

    c1 = np.mean(points1, axis=0)
    c2 = np.mean(points2, axis=0)
    points1 -= c1
    points2 -= c2
    
    s1 = np.std(points1)
    s2 = np.std(points2)
    points1 /= s1
    points2 /= s2

    U, S, Vt = np.linalg.svd(points1.T * points2)
    R = (U * Vt).T
    
    return np.hstack(((s2/s1)*R, c2.T-(s2/s1)*R*c1.T))

def normalColor(a, b):
    """颜色匹配"""
    ksize = (11, 11)
    aGauss = cv2.GaussianBlur(a, ksize, sigmaX=0)
    bGauss = cv2.GaussianBlur(b, ksize, sigmaX=0)
    
    weight = aGauss / bGauss
    where_are_inf = np.isinf(weight)
    weight[where_are_inf] = 0
    
    return b * weight

# ==================== 主程序 ====================

if __name__ == "__main__":
    # 初始化检测器
    detector = dlib.get_frontal_face_detector()
    predictor = dlib.shape_predictor("shape_predictor_68_face_landmarks.dat")

    # 读取图像
    a = cv2.imread("img_19.png")  # 目标图
    b = cv2.imread("img_16.png")  # 源图
    b = cv2.flip(b, 1)  # 水平翻转

    # Step 1: 提取关键点
    print("正在提取人脸关键点...")
    aKeyPoints = getKeyPoints(a)
    bKeyPoints = getKeyPoints(b)

    # Step 2: 生成掩膜
    print("正在生成人脸掩膜...")
    aMask = getFaceMask(a, aKeyPoints)
    bMask = getFaceMask(b, bKeyPoints)

    # Step 3: 计算变换矩阵
    print("正在计算仿射变换...")
    M = getM(aKeyPoints[POINTStuple], bKeyPoints[POINTStuple])

    # Step 4: 仿射变换
    dsize = a.shape[:2][::-1]
    bMaskWarp = cv2.warpAffine(bMask, M, dsize,
                               borderMode=cv2.BORDER_TRANSPARENT,
                               flags=cv2.WARP_INVERSE_MAP)
    
    mask = np.max([aMask, bMaskWarp], axis=0)
    
    bWrap = cv2.warpAffine(b, M, dsize,
                          borderMode=cv2.BORDER_TRANSPARENT,
                          flags=cv2.WARP_INVERSE_MAP)

    # Step 5: 颜色匹配
    print("正在进行颜色匹配...")
    bcolor = normalColor(a, bWrap)

    # Step 6: 融合
    print("正在融合图像...")
    out = a * (1.0 - mask) + bcolor * mask

    # 显示和保存结果
    cv2.imshow("Original A", a)
    cv2.imshow("Original B", b)
    cv2.imshow("Result", out/255)
    cv2.imwrite("result.png", out)
    
    print("换脸完成!结果已保存为 result.png")
    cv2.waitKey(0)
    cv2.destroyAllWindows()

相关推荐
空白诗4 小时前
CANN ops-nn 算子解读:Stable Diffusion 图像生成中的 Conv2D 卷积实现
深度学习·计算机视觉·stable diffusion
lxs-5 小时前
CANN计算机视觉算子库ops-cv全面解析:图像处理与目标检测的高性能引擎
图像处理·目标检测·计算机视觉
qq_12498707538 小时前
基于JavaWeb的大学生房屋租赁系统(源码+论文+部署+安装)
java·数据库·人工智能·spring boot·计算机视觉·毕业设计·计算机毕业设计
杜子不疼.9 小时前
CANN计算机视觉算子库ops-cv的图像处理与特征提取优化实践
图像处理·人工智能·计算机视觉
张人玉9 小时前
VisionPro 定位与卡尺测量学习笔记
笔记·学习·计算机视觉·vsionprp
勾股导航9 小时前
OpenCV图像坐标系
人工智能·opencv·计算机视觉
格林威10 小时前
Baumer相机玻璃制品裂纹自动检测:提高透明材质检测精度的 6 个关键步骤,附 OpenCV+Halcon 实战代码!
人工智能·opencv·视觉检测·材质·工业相机·sdk开发·堡盟相机
哈__11 小时前
CANN加速Image-to-Image转换:风格迁移与图像编辑优化
人工智能·计算机视觉
渡我白衣13 小时前
信而有征——模型评估、验证与可信部署的完整体系
人工智能·深度学习·神经网络·目标检测·机器学习·计算机视觉·自然语言处理