0%

利用人脸检测关键点实现简单的图像分割合并操作

人脸关键点

使用Google的人脸检测工具MediaPipe来做人脸关键点的检测,可以按照Face Mesh Detection with Python and OpenCV的操作安装MediaPipe并可视化关键点。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
import cv2
import mediapipe as mp

#Face Mesh

mp_face_mesh = mp.solutions.face_mesh
face_mesh = mp_face_mesh.FaceMesh()

#Image

image = cv2.imread("/home/python/OpenCV/faceMash/image1.jpg")
height, width, _ = image.shape
rgb_image = cv2.cvtColor(image, cv2.COLOR_BGR2RGB)

#Facial landmarks
result = face_mesh.process(image)


for facial_landmarks in result.multi_face_landmarks:
for i in range(0, 468):

pt1 = facial_landmarks.landmark[i]
x = int(pt1.x * width)
y = int(pt1.y * height)

cv2.circle(image, (x,y), 2, (100,100,0), -1)
#cv2.putText(image, str(i), (x,y), 0,1,(0,0,0))



cv2.imshow("Face Mesh detection", image)
cv2.waitKey(0)

人脸特征点检测指南给出了人脸关键点landmarks序列的序号分布,可以通过关键点的序号粗略圈出感兴趣范围。

比如眉毛大致范围:

1
2
3
4
# 左下角,逆时针
left_eye = [46, 53, 52, 65, 55, 107, 66, 105, 63, 70]
# 右下角,顺时针
right_eye = [276, 283, 282, 295, 285, 336, 296, 334, 293, 300]

同样大小图片的同一范围做mask以及合并操作

  1. 使用opencv的cv2.drawContours生成mask遮罩
  2. 使用numpy的位操作numpy.invertnumpy.bitwist_andnumpy.bitwist_or,能够很方便的完成图片的分割、取反以及合并操作
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
import cv2
import mediapipe as mp
import numpy as np

#Face Mesh

mp_face_mesh = mp.solutions.face_mesh
face_mesh = mp_face_mesh.FaceMesh()

#Image

image = cv2.imread("faceinput.png")
height, width, _ = image.shape
rgb_image = cv2.cvtColor(image, cv2.COLOR_BGR2RGB)

#Facial landmarks
result = face_mesh.process(image)

# 左下角,逆时针
left_eye = [46, 53, 52, 65, 55, 107, 66, 105, 63, 70]
# 右下角,顺时针
right_eye = [276, 283, 282, 295, 285, 336, 296, 334, 293, 300]

left_pts = [[]]
right_pts = [[]]
for facial_landmarks in result.multi_face_landmarks:
for i in range(0, 468):

if i in right_eye or i in left_eye:
pt1 = facial_landmarks.landmark[i]
x = int(pt1.x * width)
y = int(pt1.y * height)

cv2.circle(image, (x,y), 2, (100,100,0), -1)
#cv2.putText(image, str(i), (x,y), 0,1,(0,0,0))

for i in left_eye:
pt1 = facial_landmarks.landmark[i]
x = int(pt1.x * width)
y = int(pt1.y * height)
left_pts[0].append([x, y])

for i in right_eye:
pt1 = facial_landmarks.landmark[i]
x = int(pt1.x * width)
y = int(pt1.y * height)
right_pts[0].append([x, y])

grayscaleImage = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
grayscaleImage = cv2.cvtColor(grayscaleImage, cv2.COLOR_GRAY2BGR)
maskImage = np.zeros_like(image)
cv2.drawContours(maskImage, np.array(left_pts), 0, (255, 255, 255), -1)
cv2.drawContours(maskImage, np.array(right_pts), 0, (255, 255, 255), -1)
extractedImage=np.bitwise_and(grayscaleImage, maskImage)

# gray image
# maskImage = np.zeros_like(grayscaleImage)
# cv2.drawContours(maskImage, np.array(left_pts), 0, 255, -1)
# cv2.drawContours(maskImage, np.array(right_pts), 0, 255, -1)
# extractedImage=np.bitwise_and(grayscaleImage, maskImage)

invert_maskImage = np.invert(maskImage)
other = cv2.imread("face2.png")
# other_grayscaleImage = cv2.cvtColor(other, cv2.COLOR_BGR2GRAY)
extractedOther = np.bitwise_and(other, invert_maskImage)

res = np.bitwise_or(extractedImage, extractedOther)

# cv2.imwrite("res.png", res)
cv2.imshow("Face Mesh detection", extractedImage)
cv2.waitKey(0)

参考