opencv深度学习:面部特征点匹配与图像融合--换脸

embedded/2024/10/25 5:22:44/

原理

通过使用深度学习库Dlib和计算机视觉库OpenCV,实现两幅人脸图像的特征点检测、特征点匹配、图像融合,以及颜色归一化。通过这个过程,我们能够将一张人脸图像的特征(如表情、发型)无缝地融合到另一张人脸图像上。

分析

使用了Dlib的68个面部特征点检测器来精确地定位人脸特征,并通过OpenCV的图像处理功能来生成掩模和进行图像融合。仿射变换矩阵的计算和应用是实现特征点匹配的关键步骤,而颜色归一化则确保了融合后的图像在颜色上更加自然和协调。

代码步骤

  1. 导入必要的库:导入OpenCV、Dlib和NumPy库,用于图像处理和数学运算。

    # 导入必要的库
    import cv2
    import dlib
    import numpy as np
  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)
  3. 定义函数getfacemask:该函数用于根据给定的面部特征点生成一个掩模图像,该掩模图像包含了人脸的轮廓。

    # 定义函数getfacemask,用于生成面部掩模
    def getfacemask(im, keypoints):im = np.zeros(im.shape[:2], dtype=np.float64)for p in points:point = cv2.convexHull(keypoints[p])cv2.fillConvexPoly(im, point, color=1)im = np.array([im, im, im]).transpose((1, 2, 0))im = cv2.GaussianBlur(im, (25, 25), 0)return im
  4. 定义函数getm:该函数用于计算两个特征点集之间的仿射变换矩阵。

    # 定义函数getm,用于计算两个点集之间的仿射变换矩阵
    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 -= c1points2 -= c2s1 = np.std(points1)s2 = np.std(points2)points1 /= s1points2 /= s2u, s, vt = np.linalg.svd(points1.T * points2)r = (u * vt).Treturn np.hstack(((s2 / s1) * r, c2.T - (s2 / s1) * r * c1.T))
  5. 定义函数getkeypoints:该函数用于检测图像中的人脸,并获取68个面部特征点。

    # 定义函数getkeypoints,用于检测图像中的人脸并获取68个面部特征点
    def getkeypoints(im):rects = dector(im, 1)shape = predictor(im, rects[0])s = np.matrix([[p.x, p.y] for p in shape.parts()])return s
  6. 定义函数normalcolor:该函数用于颜色归一化,使得融合后的图像颜色更加自然。

    # 定义函数normalcolor,用于颜色归一化
    def normalcolor(a, b):ksize = (111, 111)agauss = cv2.GaussianBlur(a, ksize, 0)bgauss = cv2.GaussianBlur(b, ksize, 0)weight = agauss / bgausswhere_are_inf = np.isinf(weight)weight[where_are_inf] = 0return b * weight
  7. 读取图像:读取两张人脸图像woman1.pngwoman2.png

    # 读取两张人脸图像
    a = cv2.imread("woman1.png")
    b = cv2.imread("woman2.png")
  8. 初始化人脸检测器和特征点预测器:使用Dlib库初始化人脸检测器和特征点预测器。

    # 初始化人脸检测器和特征点预测器
    dector = dlib.get_frontal_face_detector()
    predictor = dlib.shape_predictor("shape_predictor_68_face_landmarks.dat")
  9. 获取特征点:对两张图像分别获取面部特征点。

    # 获取两张图像的面部特征点
    akeypoints = getkeypoints(a)
    bkeypoints = getkeypoints(b)
  10. 生成掩模图像:对两张图像分别生成掩模图像。

    # 复制第二张图像,用于后续显示
    boriginal = b.copy()# 生成第一张图像的面部掩模
    amask = getfacemask(a, akeypoints)
    cv2.imshow("amask", amask)
    cv2.waitKey()# 生成第二张图像的面部掩模
    bmask = getfacemask(b, bkeypoints)
    cv2.imshow("bmask", bmask)
    cv2.waitKey()
  11. 计算仿射变换矩阵:计算两张图像特征点之间的仿射变换矩阵。

    # 计算仿射变换矩阵
    m = getm(akeypoints[pointstuple], bkeypoints[pointstuple])
  12. 应用仿射变换:将第二张图像的掩模和特征点应用仿射变换,以匹配第一张图像。

    # 获取第一张图像的尺寸
    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(0)# 计算最终的掩模
    mask = np.max([amask, bmaskwarp], axis=0)
    cv2.imshow("mask", mask)
    cv2.waitKey(0)# 应用仿射变换到第二张图像上
    bwarp = cv2.warpAffine(b, m, dsize, borderMode=cv2.BORDER_TRANSPARENT, flags=cv2.WARP_INVERSE_MAP)
    cv2.imshow("bwarp", bwarp)
    cv2.waitKey()
  13. 生成融合图像:通过掩模和颜色归一化,将两张图像融合在一起。

    # 进行颜色归一化
    bcolor = normalcolor(a, bwarp)
    cv2.imshow("bcolor", bcolor)
    cv2.waitKey()# 将两张图像融合
    out = a * (1.0 - mask) + bcolor * mask
    cv2.imshow("a", a)
    cv2.imshow("b", boriginal)
    cv2.imshow("out", out / 255)
    cv2.waitKey()
    cv2.destroyAllWindows()

运行结果

完整代码


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 getfacemask(im,keypoints):im=np.zeros(im.shape[:2],dtype=np.float64)for p in points:point=cv2.convexHull(keypoints[p])cv2.fillConvexPoly(im,point,color=1)im=np.array([im,im,im]).transpose((1,2,0))im=cv2.GaussianBlur(im,(25,25),0)return imdef 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 -= c1points2 -= c2s1=np.std(points1)s2=np.std(points2)points1 /= s1points2 /= s2u,s,vt=np.linalg.svd(points1.T*points2)r=(u*vt).Treturn np.hstack(((s2 / s1) * r, c2.T - (s2 / s1) * r * c1.T))def getkeypoints(im):rects=dector(im,1)shape=predictor(im,rects[0])s=np.matrix([[p.x,p.y] for p in shape.parts()])return sdef normalcolor(a,b):ksize=(111,111)agauss=cv2.GaussianBlur(a,ksize,0)bgauss=cv2.GaussianBlur(b,ksize,0)weight=agauss/bgausswhere_are_inf=np.isinf(weight)weight[where_are_inf]=0return b*weighta=cv2.imread("woman1.png")
b=cv2.imread("woman2.png")
dector=dlib.get_frontal_face_detector()
predictor=dlib.shape_predictor("shape_predictor_68_face_landmarks.dat")
akeypoints=getkeypoints(a)
bkeypoints=getkeypoints(b)
boriginal=b.copy()
amask=getfacemask(a,akeypoints)
cv2.imshow("amask",amask)
cv2.waitKey()bmask=getfacemask(b,bkeypoints)
cv2.imshow("bmask",bmask)
cv2.waitKey()m=getm(akeypoints[pointstuple],bkeypoints[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(0)
mask=np.max([amask,bmaskwarp],axis=0)
cv2.imshow("mask",mask)
cv2.waitKey(0)bwarp=cv2.warpAffine(b,m,dsize,borderMode=cv2.BORDER_TRANSPARENT,flags=cv2.WARP_INVERSE_MAP)
cv2.imshow("bwarp",bwarp)
cv2.waitKey()bcolor=normalcolor(a,bwarp)
cv2.imshow("bcolor",bcolor)
cv2.waitKey()out=a*(1.0-mask)+bcolor*mask
cv2.imshow("a",a)
cv2.imshow("b",boriginal)
cv2.imshow("out",out/255)
cv2.waitKey()
cv2.destroyAllWindows()

总结

展示了如何使用深度学习计算机视觉技术来实现人脸特征的检测、匹配和图像融合。通过这个过程,我们可以在不同的人脸图像之间转移特定的特征,为面部表情合成、虚拟试妆等应用提供了技术支持。实验结果表明,该方法在处理人脸图像时具有较高的精确度和自然度。


http://www.ppmy.cn/embedded/132249.html

相关文章

maven本地打jar包依赖

本地工程的pom文件中引入了mysql依赖,但是在maven库中没有拉下来,可以到mysql官网下载jar包,使用maven手动打包到本地仓库中: 官网地址:MySQL :: Download MySQL Connector/J (Archived Versions) 在jar包所在位置的路…

Java 使用 itextpdf 自定义 生成 pdf

Java 使用 itextpdf 自定义 生成 pdf maven 依赖实现docker 服务 字体文件找不到问题 maven 依赖 <!-- iText 7 --> <dependency><groupId>com.itextpdf</groupId><artifactId>itext7-core</artifactId><version>7.2.3</version…

软考:缓存分片和一致性哈希

缓存分片技术是一种将数据分散存储在多个节点上的方法&#xff0c;它在分布式缓存系统中尤为重要。这项技术的核心目的是提高系统的性能和可扩展性&#xff0c;同时确保数据的高可用性。以下是缓存分片技术的一些关键点&#xff1a; 数据分片&#xff1a;缓存分片涉及将数据分成…

Axios 基本使用

Axios 是一个异步请求技术,核心作用就是用来在页面中发送异步请求,并获取对应数据在页面中渲染 页面局部更新技术 Ajax 中文网站:https://www.kancloud.cn/yunye/axios/234845 安装: <script src"https://unpkg.com/axios/dist/axios.min.js"></script&g…

Android 10.0 截屏流程

通常未通过特殊定制的 Android 系统&#xff0c;截屏都是经过同时按住音量下键和电源键来截屏。本篇文章就只讨论使用这些特殊按键来进行截屏。 这里我们就要明白事件是在哪里进行分发拦截的。通过源码的分析&#xff0c;我们发现是在PhoneWindowManager.java 中。 PhoneWindow…

Vue项目实战-新能源汽车可视化(一)(持续更新中)

一.项目代码 1.App.vue <template><!-- 模板--><div id"wrapper"><div style"width: 100%"><el-tabs v-model"activeName" id"tabs"> <!-- 标签栏里包含了三个标签面板&#xff0c;分别是研发与维…

css动画烟花秀__烟花效果

先看效果 CSS烟花秀 这是一个在HTML5页面&#xff0c;实现烟花效果的例子 以下为实现代码 <!DOCTYPE html> <html lang"en"><head><meta charset"UTF-8"><meta name"viewport" content"widthdevice-width, in…

多模态大语言模型(MLLM)-Blip3/xGen-MM

论文链接&#xff1a;https://www.arxiv.org/abs/2408.08872 代码链接&#xff1a;https://github.com/salesforce/LAVIS/tree/xgen-mm 本次解读xGen-MM (BLIP-3): A Family of Open Large Multimodal Models 可以看作是 [1] Blip: Bootstrapping language-image pre-training…