使用OpenCV和Dlib实现面部换脸
创作时间:
作者:
@小白创作中心
使用OpenCV和Dlib实现面部换脸
引用
CSDN
1.
https://blog.csdn.net/m0_73697499/article/details/143066484
面部换脸技术是计算机视觉领域的一个有趣应用,它通过检测面部特征点并进行图像融合,实现将一张人脸替换到另一张人脸上的效果。本文将详细介绍如何使用OpenCV和Dlib库来实现这一功能。
环境搭建
首先,我们需要安装必要的库。请确保已经安装了opencv-python、numpy以及dlib。如果还未安装,可以通过以下命令进行安装:
pip install opencv-python numpy dlib
注意:由于dlib依赖于CMake和其他一些编译工具,因此在安装过程中可能会遇到一些配置问题。如果安装遇到困难,建议查阅官方文档或寻求社区帮助。
实现步骤
我们将通过以下几个步骤来实现面部特征点检测及面部融合:
- 定义关键点集合:首先定义一组面部特征点集合,包括下巴、眉毛、眼睛、鼻子、嘴巴等部位的关键点。
- 获取面部掩模:根据关键点生成面部的二值掩模。
- 求解仿射变换矩阵:通过关键点计算两幅图像之间的仿射变换矩阵。
- 图像融合:利用仿射变换矩阵将一张图像的脸部特征融合到另一张图像中。
代码实现
- 定义关键点集合
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:
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 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
- 图像融合
def normalColor(a, b):
aGauss = cv2.GaussianBlur(a, (111, 111), 0)
bGauss = cv2.GaussianBlur(b, (111, 111), 0)
weight = aGauss / bGauss
where_are_inf = np.isinf(weight)
weight[where_are_inf] = 0
return b * weight
- 主流程
导入图片
a = cv2.imread("data/hg.png") # 换脸A图片
b = cv2.imread("data/people1.png") # 换脸B图片
导入模型
detector = dlib.get_frontal_face_detector()
predictor = dlib.shape_predictor("data/shape_predictor_68_face_landmarks.dat")
获取关键点,获取图片的人脸掩膜
aKeyPoints = getKeypoints(a) # 获取A图片的68关键点
bKeyPoints = getKeypoints(b) # 获取B图片的68关键点
bOriginal = b.copy() # 不对原来的图片b进行破坏和修改
aMask = getFaceMask(a, aKeyPoints) # 获取图片A的人脸掩膜
cv2.imshow("aMask", aMask)
cv2.waitKey()
bMask = getFaceMask(b, bKeyPoints) # 获取图片B的人脸掩膜
cv2.imshow("bMask", bMask)
cv2.waitKey()
求出b脸仿射变换到a脸的变换矩阵
M = getM(aKeyPoints[POINTStuple], bKeyPoints[POINTStuple])
"""将b的脸部(bmask)根据M仿射变换到a上"""
dsize = a.shape[:2][::-1]
# 目标输出与图像a大小一致
# 需要注意,shape是〈行,列〉,warpAffine参数dsize是〈列,行〉
# 使用a.shape[2:][:,::-1],获取a的〈列,行〉
# 函数warpAffine(src, M, dsize, dst=None, flags=None, borderMode=None, borderValue=None)
# src:输入图像
# M:运算矩阵;2行3列的,
# dsize:运算后矩阵的大小,也就是输出图片的尺寸
# dst:输出图像
# flags:插值方法的组合,与resize函数中的插值一样,可以查看cv2.resize
# borderMode:边界模式, BORDER_TRANSPARENT表示边界透明
# borderValue:在恒定边框的情况下使用的borderValue值,默认情况下,它是 0
bMaskWarp = cv2.warpAffine(bMask, M, dsize,
borderMode=cv2.BORDER_TRANSPARENT,
flags=cv2.WARP_INVERSE_MAP)
cv2.imshow("bMaskWarp", bMaskWarp)
cv2.waitKey()
使用仿射矩阵M,将b映射到a
bWrap = cv2.warpAffine(b, M, dsize,
borderMode=cv2.BORDER_TRANSPARENT,
flags=cv2.WARP_INVERSE_MAP)
cv2.imshow("bWrap", bWrap)
cv2.waitKey()
求b图片的仿射到图片a的颜色值
# 求b图片的仿射到图片a的颜色值,b的颜色值改为a的颜色
bcolor = normalColor(a, bWrap)
cv2.imshow("bcolor", bcolor)
cv2.waitKey()
输出 换脸结果
# ===========step8:换脸(mask区域用bcolor,imask区城用a)=============
out = a * (1.0 - mask) + bcolor * mask
# =========输出原始人脸、换脸结果===============
cv2.imshow("a", a)
cv2.imshow("b", bOriginal)
cv2.imshow("out", out / 255)
cv2.waitKey()
cv2.destroyAllWindows()
代码解析
- 定义关键点集合:根据68个面部特征点的位置,定义了不同的面部区域。
- 获取面部掩模:根据面部特征点生成面部的二值掩模。
- 求解仿射变换矩阵:通过关键点计算两幅图像之间的仿射变换矩阵。
- 图像融合:利用仿射变换矩阵将一张图像的脸部特征融合到另一张图像中,并调整颜色使其更加自然。
总结
通过上述代码,我们实现了基于OpenCV和Dlib的面部特征点检测及面部融合功能。面部特征点检测是很多计算机视觉应用的基础,而面部融合则是其中一种有趣的应用实例。希望本文能够帮助你更好地理解和应用这些技术,同时也鼓励你在实践中不断探索新的应用场景和技术。
热门推荐
猪肉常见部位的特点及吃法,看这一篇就够了
陈婷与张艺谋:一段跨越31岁的爱情传奇
波风水门教你如何利用属性克制
《火影忍者》属性克制大揭秘:谁才是最强忍者?
武汉周边6个最美古镇,周末自驾好去处
这样做出来的红烧排骨,不但好吃而且营养
精准职业定位:提升求职竞争力的关键
口咽操:告别打鼾,守护健康睡眠
打鼾不止是"呼噜":睡眠呼吸暂停的真相与应对之道
健康饮食巧改善,告别打鼾困扰
《新愚公移山》:传统艺术与现代动画的完美融合
愚公移山:新时代的坚持与突破
从李跃儿芭学园戏剧节到动画片:《愚公移山》的教育启示
《蛊真人》:独特的修炼体系与宏大的世界观
智能投资:人工智能在现代股票交易中的作用
蜜桃酸奶三明治高颜值低卡又饱腹,多少次早起就为这一口,真的太好吃了!
鲅鱼圈区自驾游:网红景点打卡全攻略
冬日探秘:鲅鱼圈熊岳古镇的雪景奇观
鲅鱼圈自驾游攻略:夏日避暑胜地
守护生命中枢:如何保护你的脑垂体健康
脑垂体工作原理大揭秘:腺垂体VS神经垂体
协和医院专家推荐:月瘦八斤不反弹减肥食谱
秋冬减肥秘籍:国家卫健委&丁香医生教你吃出好身材!
原地跑步减肥,你真的会吗?
茯苓搭配麦冬:98岁土郎中秘制美食,省钱又管用
茯苓泡水喝的正确方法
安乃近:中美用药差异大揭秘
安乃近使用需谨慎:高风险人群禁用,这些药物更安全
秋冬必备:泰诺林&美林退烧指南
科技教育:培养未来人才的关键