import cv2import dlibimport numpy as npimport mathPREDICTOR_PATH = "E:/Testcomptition/shape_predictor_68_face_landmarks.dat"predictor = dlib.shape_predictor(PREDICTOR_PATH) # 用来预测关键点detector = dlib.get_frontal_face_detector()class FaceDetector:def resize(self,image, width=1200): # 将待检测的image进行resizer = width * 1.0 / image.shape[1]dim = (width, int(image.shape[0] * r))resized = cv2.resize(image, dim, interpolation=cv2.INTER_AREA)return resizeddef detect(self, image):# image = self.resize(image, width=1200)detector = dlib.get_frontal_face_detector()gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)rects = detector(gray, 1)# return the rectangles representing boundinb# boxes around the facesreturn rectsdef rect_to_bb(self,rect): # 获得人脸矩形的坐标信息x = rect.left()y = rect.top()w = rect.right() - xh = rect.bottom() - yreturn (x, y, w, h)def render(self,frame,rect):rects = self.detect(frame)for (i, rect) in enumerate(rects):(x, y, w, h) = self.rect_to_bb(rect)cv2.rectangle(frame, (x, y), (x + w, y + h), (0, 255, 0), 2)cv2.putText(frame, "Face", (x + 10, y + 10), cv2.FONT_HERSHEY_SIMPLEX, 0.5, (0, 255, 0), 2)return frameclass FaceAligner:def detect(self, image):# image = self.resize(image, width=1200)detector = dlib.get_frontal_face_detector()gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)rects = detector(gray, 1)# return the rectangles representing boundinb# boxes around the facesreturn rectsdef rect_to_bb(self,rect): # 获得人脸矩形的坐标信息x = rect.left()y = rect.top()w = rect.right() - xh = rect.bottom() - yreturn (x, y, w, h)def resize(self,image, width=1200): # 将待检测的image进行resizer = width * 1.0 / image.shape[1]dim = (width, int(image.shape[0] * r))resized = cv2.resize(image, dim, interpolation=cv2.INTER_AREA)return resizeddef shape_to_np(shape, dtype="int"): # 将包含68个特征的的shape转换为numpy array格式coords = np.zeros((68, 2), dtype=dtype)for i in range(0, 68):coords[i] = (shape.part(i).x, shape.part(i).y)return coordsdef rect_to_bb(self,rect): # 获得人脸矩形的坐标信息x = rect.left()y = rect.top()w = rect.right() - xh = rect.bottom() - yreturn (x, y, w, h)def face_alignment(faces):PREDICTOR_PATH = "E:/Testcomptition/shape_predictor_68_face_landmarks.dat"predictor = dlib.shape_predictor(PREDICTOR_PATH) # 用来预测关键点faces_aligned = []for face in faces:rec = dlib.rectangle(0, 0, face.shape[0], face.shape[1])shape = predictor(np.uint8(face), rec) # 注意输入的必须是uint8类型order = [36, 45, 30, 48, 54] # left eye, right eye, nose, left mouth, right mouth 注意关键点的顺序,这个在网上可以找for j in order:x = shape.part(j).xy = shape.part(j).ycv2.circle(face, (x, y), 2, (0, 0, 255), -1)eye_center = ((shape.part(36).x + shape.part(45).x) * 1. / 2, # 计算两眼的中心坐标(shape.part(36).y + shape.part(45).y) * 1. / 2)dx = (shape.part(45).x - shape.part(36).x) # note: right - rightdy = (shape.part(45).y - shape.part(36).y)angle = math.atan2(dy, dx) * 180. / math.pi # 计算角度RotateMatrix = cv2.getRotationMatrix2D(eye_center, angle, scale=1) # 计算仿射矩阵RotImg = cv2.warpAffine(face, RotateMatrix, (face.shape[0], face.shape[1])) # 进行放射变换,即旋转faces_aligned.append(RotImg)return faces_aligneddef align(self,frame,rects):#函数功能:检测人脸的关键点#参数: frame(array) – 输入图像#rect(list) – 图像中人脸的坐标(左上角和右下角的坐标)#返回(n*2 list):检测到人脸的关键点坐标,是一个 n*2 的数组,n为检测# #到的关键点数量,每个元素代表了一个关键点的坐标gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)# rects = detector(gray, 1)shapes = []for (i, rect) in enumerate(rects):shape = predictor(gray, rect)coords = np.zeros((68, 2), dtype="int")for i in range(0, 68):coords[i] = (shape.part(i).x, shape.part(i).y)shape = coords# print(len(shape))# print(shape)shapes.append(shape)return shapesdef crop_face(self,frame, points):# 函数功能:在原始图片中把人脸截取出来,并经过旋转缩放使得脸部角度正确# 得到一个 178*218 的图片# 参数:frame(array) – 原始图像# points(n*2 list) – 一个人脸的关键点坐标# 返回(array):经过裁剪、旋转、缩放后得到的脸部图片rects=self.detect(frame)src_faces = []for (i, rect) in enumerate(rects):(x, y, w, h) = self.rect_to_bb(rect)detect_face = frame[y:y + h, x:x + w] # 根据rect裁减出# cv2.imshow("detect_face", detect_face)src_faces.append(detect_face)# cv2.rectangle(frame, (x, y), (x + w, y + h), (0, 255, 0), 2)# cv2.putText(frame, "Face: {}".format(i + 1), (x - 10, y - 10), cv2.FONT_HERSHEY_SIMPLEX, 0.5, (0, 255, 0),# 2)PREDICTOR_PATH = "E:/Testcomptition/shape_predictor_68_face_landmarks.dat"predictor = dlib.shape_predictor(PREDICTOR_PATH) # 用来预测关键点faces_aligned = []for face in src_faces:rec = dlib.rectangle(0, 0, face.shape[0], face.shape[1])shape = predictor(np.uint8(face), rec) # 注意输入的必须是uint8类型order = [36, 45, 30, 48, 54] # left eye, right eye, nose, left mouth, right mouth 注意关键点的顺序,这个在网上可以找for j in order:x = shape.part(j).xy = shape.part(j).y# cv2.circle(face, (x, y), 2, (0, 0, 255), -1)eye_center = ((shape.part(36).x + shape.part(45).x) * 1. / 2, # 计算两眼的中心坐标(shape.part(36).y + shape.part(45).y) * 1. / 2)dx = (shape.part(45).x - shape.part(36).x) # note: right - rightdy = (shape.part(45).y - shape.part(36).y)angle = math.atan2(dy, dx) * 180. / math.pi # 计算角度RotateMatrix = cv2.getRotationMatrix2D(eye_center, angle, scale=1) # 计算仿射矩阵RotImg = cv2.warpAffine(face, RotateMatrix, (face.shape[0], face.shape[1])) # 进行放射变换,即旋转faces_aligned.append(RotImg)# for face in faces_aligned:#cv2.imshow("align_face_{}".format(i), face)#i = i + 1# cv2.waitKey(0)return faces_aligneddef render(self,frame, points):# 函数功能:在原始图片中把人脸的关键点标上红点# 参数: frame(array) – 原始图像# points(n*2 list) – 一个人脸的关键点坐标# 返回(array)::把人脸的关键点标上红点之后的图像for shape in points:for (x, y) in shape:cv2.circle(frame, (x, y), 2, (0, 255, 0), -1)return frameimport testfacedetectokif __name__ == '__main__':image_file = 'E:/Testcomptition/subject/competition_2/exam3/tests/103011.jpg'frame = cv2.imread(image_file)rects = FaceDetector().detect(frame)print("rects",rects)detect_face = FaceDetector().render(frame, rects)cv2.imshow("detect_face",detect_face)frame1 = cv2.imread(image_file)face_aligner=FaceAligner()key_points = face_aligner.align(frame1, rects)# print(key_points)crop_frames = face_aligner.crop_face(frame1, key_points)points_frame = face_aligner.render(frame1, key_points)print(crop_frames)i = 0for face in crop_frames:cv2.imshow("det_{}".format(i), face)i = i + 1cv2.imshow("crop_face", points_frame)# 等待“q”按下,关闭窗口cv2.waitKey(0)
参考自:【Dlib】人脸检测、特征点检测、人脸对齐、人脸识别_夏洛的网的博客-CSDN博客_人脸检测 人脸对齐 特征提取