OpenCV深度学习:面部特征点匹配与图像融合--换脸
创作时间:
作者:
@小白创作中心
OpenCV深度学习:面部特征点匹配与图像融合--换脸
引用
CSDN
1.
https://blog.csdn.net/mohanyelong/article/details/143219392
本文将介绍如何使用OpenCV和Dlib实现面部特征点匹配与图像融合,从而实现人脸替换的效果。通过深度学习库Dlib和计算机视觉库OpenCV,我们可以实现两幅人脸图像的特征点检测、特征点匹配、图像融合,以及颜色归一化。
原理
通过使用深度学习库Dlib和计算机视觉库OpenCV,实现两幅人脸图像的特征点检测、特征点匹配、图像融合,以及颜色归一化。通过这个过程,我们能够将一张人脸图像的特征(如表情、发型)无缝地融合到另一张人脸图像上。
分析
使用了Dlib的68个面部特征点检测器来精确地定位人脸特征,并通过OpenCV的图像处理功能来生成掩模和进行图像融合。仿射变换矩阵的计算和应用是实现特征点匹配的关键步骤,而颜色归一化则确保了融合后的图像在颜色上更加自然和协调。
代码步骤
- 导入必要的库:导入OpenCV、Dlib和NumPy库,用于图像处理和数学运算。
# 导入必要的库
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)
- **定义函数
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
- **定义函数
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 -= 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))
- **定义函数
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
- **定义函数
normalcolor
**:该函数用于颜色归一化,使得融合后的图像颜色更加自然。
# 定义函数normalcolor,用于颜色归一化
def normalcolor(a, b):
ksize = (111, 111)
agauss = cv2.GaussianBlur(a, ksize, 0)
bgauss = cv2.GaussianBlur(b, ksize, 0)
weight = agauss / bgauss
where_are_inf = np.isinf(weight)
weight[where_are_inf] = 0
return b * weight
- 读取图像:读取两张人脸图像
woman1.png
和
woman2.png
。
# 读取两张人脸图像
a = cv2.imread("woman1.png")
b = cv2.imread("woman2.png")
- 初始化人脸检测器和特征点预测器:使用Dlib库初始化人脸检测器和特征点预测器。
# 初始化人脸检测器和特征点预测器
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()
运行结果
完整代码
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 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 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
def normalcolor(a,b):
ksize=(111,111)
agauss=cv2.GaussianBlur(a,ksize,0)
bgauss=cv2.GaussianBlur(b,ksize,0)
weight=agauss/bgauss
where_are_inf=np.isinf(weight)
weight[where_are_inf]=0
return b*weight
a=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()
总结
展示了如何使用深度学习和计算机视觉技术来实现人脸特征的检测、匹配和图像融合。通过这个过程,我们可以在不同的人脸图像之间转移特定的特征,为面部表情合成、虚拟试妆等应用提供了技术支持。实验结果表明,该方法在处理人脸图像时具有较高的精确度和自然度。
热门推荐
快递业激战,“利润王”中通也扛不住
科学减肥指南:三位一体打造健康体态
四肢纤细,唯独肚子胖?这次原因找到了!
厨房食材保鲜法,让你告别浪费与变质
羽毛球新手必看!百元神器+避坑指南,从握拍到扣杀一次讲透
DDR4 2133 与 DDR4 2666 内存差异及选择指南
心理素质太差了怎么办?7个方法帮你提升心理素质
全球光伏市场需求趋缓 政策与供应链的多重影响
如何在家制作天然果汁:食谱和健康益处
江苏省举办首届农业行业职业技能竞赛,农机驾驶操作员这样“比武”
十二星座的起源和历史发展:你真的了解它们吗?
不负最美春光 助力“桃花经济”
《生化危机4》:丧尸末世求生记,探寻恐怖世界下的情感波澜
贵州大学谢海波教授团队在AFM发表光催化偶联反应最新研究成果
清热利湿,明目退翳灵丹——荠菜
中国姓名文化:姓与氏有何不同,名字为何叫“名字”?
你能用磁铁来勘探黄金吗?
高管变更对企业发展的影响与应对策略
周润发:从香港之子到国际巨星的传奇人生
如何有效解决Nginx反向代理WebSocket连接时出现的错误?
摩托车载人出车祸有法律责任吗?律师解析法律责任归属
鲜花怎么养时间比较久(室内养护花卉技巧)
洛阳隋唐大运河文化博物馆:再现隋唐大运河的沧桑历史
切尔诺贝利核事故:人类历史上最大的核灾难
核心期刊发表的限制与挑战
冬季床上螨虫防治全攻略:8个实用妙招让你安心过冬
教会孩子,三步实现"过目不忘"的好记忆
心理科普 | 如何整治许沁的恋爱脑?
新能源汽车年检新规发布:电池安全成必检项目
如何有效清理苹果手机内存垃圾,提升使用体验的实用指南