最近在做人脸相关课题,找个地方保存一下部分代码。
用的dlib是81个关键点,GitHub网址:https://github.com/codeniko/shape_predictor_81_face_landmarks
- #读取视频,检测一帧中的人脸,并在图像中标出关键点,同时打印出关键点的坐标。
- import dlib
- import numpy as np
- import cv2
- from matplotlib import pyplot as plt
-
- cap = cv2.VideoCapture('视频路径')
-
- predictor_path = "shape_predictor_81_face_landmarks.dat的路径"
-
- detector = dlib.get_frontal_face_detector()
- predictor = dlib.shape_predictor(predictor_path)
-
- while(True):
- ret, frame = cap.read()
- # 取灰度
- img_gray = cv2.cvtColor(frame, cv2.COLOR_RGB2GRAY)
- # 人脸数rects
- rects = detector(img_gray, 0)
- for i in range(len(rects)):
- landmarks = np.matrix([[p.x, p.y] for p in predictor(frame, rects[i]).parts()])
- for idx, point in enumerate(landmarks):
- # 81点的坐标
- pos = (point[0, 0], point[0, 1])
- # 利用cv2.circle给每个特征点画一个圈,共81个
- cv2.circle(frame, pos, 2, color=(0, 255, 0))
- # 利用cv2.putText输出1-81
- font = cv2.FONT_HERSHEY_SIMPLEX
- cv2.putText(frame, str(idx + 1), pos, font, 0.3, (0, 0, 255), 1, cv2.LINE_AA)
- print("index=" + str(idx+1) + " x=" + str(pos[0]) + " y=" + str(pos[1]))
- plt.imshow(frame)
- plt.show()
- if cv2.waitKey(1) & 0xFF == ord('q'):
- print("q pressed")
- break
- cap.release()
- cv2.destroyAllWindows()
-
接下来根据上面的人脸关键点,选取ROI。
- a = np.arange(81)
- b = np.arange(81)
- # 取灰度
- img_gray = cv2.cvtColor(frame, cv2.COLOR_RGB2GRAY)
- dets = detector(img_gray, 0)
- if (len(dets) != 0):
- # 找到脸颊区域
- for i in range(len(dets)):
- landmarks = np.matrix([[p.x, p.y] for p in predictor(frame, dets[i]).parts()])
- for idx, point in enumerate(landmarks):
- # 68点的坐标
- pos = (point[0, 0], point[0, 1])
- # ROI:脸颊区域
- a = a.tolist()
- b = b.tolist()
- a[idx] = point[0, 0]
- b[idx] = point[0, 1]
- a = np.array(a)
- b = np.array(b)
-
- # 额头区域
- x1 = int(a[76])
- y1 = int(b[19])
- x2 = int(a[73])
- y2 = int(b[73])
- if (x1 < 0): # 防止人脸转动,x1位置超出图像
- x1 = 0
- forehead_ROI = frame[y2:y1, x1:x2]
-
- # 脸颊区域
- x1 = int((a[2] + a[4]) / 2)
- y1 = int((b[2] + b[4]) / 2)
- y2 = int((b[2] + b[23]) / 2)
- x2 = int((a[12] + a[14]) / 2)
- if (x1 < 0):
- x1 = 0
- cheek_ROI = frame[y2:y1, x1:x2]
-
- # 检测整个人脸区域
- for k, d in enumerate(dets):
- [x1, x2, y1, y2] = [d.left(), d.right(), d.top(), d.bottom()]
- face_ROI = frames[y1:y2, x1:x2]
-