人脸网格匹配技术详解

在本文中,将探讨如何使用OpenCV和dlib这两个强大的库来从给定的图像中提取人脸,并尝试将两张不同图像中的人脸特征点进行匹配。简而言之,将尝试将两张不同图像中的人脸特征点进行网格化匹配。将使用一个预训练的模型来从人脸中提取特征点(68个特征点检测)。

人脸网格应用的工业应用

Snapchat是当今年轻一代中非常流行的一款应用,它允许用户在面部上应用多种滤镜。类似地,可以将人脸网格匹配功能添加到Snapchat或其他类似软件中,以吸引更多用户,从而增加下载量。

增强现实软件也可以在其某些用例中使用这一功能,以展示和创造更具创意的效果。

导入必要的库

import cv2 import numpy as np import dlib import requests from PIL import Image

以下是安装dlib库的步骤,这可能有些复杂,需要遵循以下步骤:

  • 安装Visual Studio(最新版本)- 参考此。
  • 在Visual Studio中,需要安装CMake包。
  • 安装完成后,再次使用pip安装CMake:pip install CMake。
  • 最后,安装dlib:pip install dlib。

下载预训练模型shape_predictor:

创建函数以从NumPy数组中提取索引

def extract_index_nparray(nparray): index = None for num in nparray[0]: index = num break return index

接下来,将从互联网上的URL加载源图像,并调整其大小。

image1 = Image.open(requests.get('https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSx8Pu1tW1uCiZPfj9K1EL6uHxbg3bOKO9XkA&usqp=CAU', stream=True).raw) image1 = image1.resize((300,300))

同样,将从互联网上的URL加载目标图像,并调整其大小。

image2 = Image.open(requests.get('https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTYX1dyl9INRo5cbvDeTILRcZVzfcMsCsE0kg&usqp=CAU', stream=True).raw) image2 = image2.resize((300,300))

将图像转换为NumPy数组并转换为灰度图

img = np.array(image1) img_gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) mask = np.zeros_like(img_gray) img2 = np.array(image2) img2_gray = cv2.cvtColor(img2, cv2.COLOR_BGR2GRAY)

为了创建与源图像大小相同的零值掩码图像,首先使用dlib加载面部检测器和面部特征点预测器,然后找到高度、宽度和通道数。

detector = dlib.get_frontal_face_detector() predictor = dlib.shape_predictor("shape_predictor_68_face_landmarks.dat") height, width, channels = img2.shape img2_new_face = np.zeros((height, width, channels), np.uint8)

图像的三角化以进行面部网格应用

首先,需要将图像传递给检测器,然后使用该对象提取特征点。之后,将提取的特征点(x和y)存储到特征点列表中。将面部网格化为三角形。这一步是面部交换的核心。这里,将每个三角形与目标图像中的相应三角形进行交换。目标图像的三角化需要与源图像的三角化具有相同的模式。这意味着连接符号的连接方式必须相同。因此,在对源图像进行三角化之后,从该三角化中获取(x和y)的索引,以便可以在目标图像上复制相同的三角化。一旦有了三角形的索引,就循环遍历它们并对目标面部进行三角化。

faces = detector(img_gray) for face in faces: landmarks = predictor(img_gray, face) landmarks_points = [] for n in range(0, 68): x = landmarks.part(n).x y = landmarks.part(n).y landmarks_points.append((x, y)) points = np.array(landmarks_points, np.int32) convexhull = cv2.convexHull(points) cv2.fillConvexPoly(mask, convexhull, 255)

Delaunay三角化是一种用于三角化图像的算法。一旦切割并包装了所有的三角形,需要将它们连接在一起。然后,需要使用三角化模式重建面部,唯一的区别是这次放置了包装的三角形。

img2_face_mask = np.zeros_like(img2_gray) img2_head_mask = cv2.fillConvexPoly(img2_face_mask, convexhull2, 255) img2_face_mask = cv2.bitwise_not(img2_head_mask)

现在面部已经准备好被替换了。取新面部和没有面部的目标图像,并将它们连接在一起。

img2_head_noface = cv2.bitwise_and(img2, img2, mask=img2_face_mask) result = cv2.add(img2_head_noface, img2_new_face)

最后,使用OpenCV内置的“seamless clone”函数自动执行此操作。需要取新面部(在第6步创建的),取原始目标图像及其掩码以切出面部,需要获取面部的中间部分。

(x, y, w, h) = cv2.boundingRect(convexhull2) center_face2 = (int((x + x + w) / 2), int((y + y + h) / 2)) seamlessclone = cv2.seamlessClone(result, img2, img2_head_mask, center_face2, cv2.NORMAL_CLONE)

最后,将输出的NumPy图像转换为Pillow的Image对象以进行可视化。

Image.fromarray(seamlessclone)
沪ICP备2024098111号-1
上海秋旦网络科技中心:上海市奉贤区金大公路8218号1幢 联系电话:17898875485