import cv2 import numpy as np import dlib from imutils import face_utils import imutils import joblib class FaceDetection(object): def __init__(self): self.detector = dlib.get_frontal_face_detector() self.predictor = joblib.load('./code/shape_predictor_68_face_landmarks_predictor.pkl') self.fa = face_utils.FaceAligner(self.predictor, desiredFaceWidth=256) def face_detect(self, frame): #frame = imutils.resize(frame, width=400) face_frame = np.zeros((10, 10, 3), np.uint8) mask = np.zeros((10, 10, 3), np.uint8) ROI1 = np.zeros((10, 10, 3), np.uint8) ROI2 = np.zeros((10, 10, 3), np.uint8) face_region = np.zeros((10, 10, 3), np.uint8) #ROI3 = np.zeros((10, 10, 3), np.uint8) status = False if frame is None: return gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY) # detect faces in the grayscale image rects = self.detector(gray, 0) # loop over the face detections #for (i, rect) in enumerate(rects): # determine the facial landmarks for the face region, then # convert the facial landmark (x, y)-coordinates to a NumPy # array #assumpion: only 1 face is detected if len(rects)>0: status = True # shape = self.predictor(gray, rects[0]) # shape = face_utils.shape_to_np(shape) # convert dlib's rectangle to a OpenCV-style bounding box # [i.e., (x, y, w, h)], then draw the face bounding box (x, y, w, h) = face_utils.rect_to_bb(rects[0]) cv2.rectangle(frame, (x, y), (x + w, y + h), (0, 255, 0), 1) if y<0: print("a") return frame, face_frame, ROI1, ROI2, status, mask #if i==0: face_frame = frame[y:y+h,x:x+w] face_region = face_frame.copy() # show the face number #cv2.putText(frame, "Face #{}".format(i + 1), (x - 10, y - 10), # cv2.FONT_HERSHEY_SIMPLEX, 0.5, (0, 255, 0), 2) # loop over the (x, y)-coordinates for the facial landmarks # and draw them on the image # for (x, y) in shape: # cv2.circle(frame, (x, y), 1, (0, 0, 255), -1) #draw facial landmarks if(face_frame.shape[:2][1] != 0): face_frame = imutils.resize(face_frame,width=256) #print(frame,'|||',gray,'|||',rects[0],type(np.array(rects[0]))) face_frame = self.fa.align(frame,gray,rects[0]) # align face grayf = cv2.cvtColor(face_frame, cv2.COLOR_BGR2GRAY) rectsf = self.detector(grayf, 0) if len(rectsf) >0: shape = self.predictor(grayf, rectsf[0]) shape = face_utils.shape_to_np(shape) for (a, b) in shape: cv2.circle(face_frame, (a, b), 1, (0, 0, 255), -1) #draw facial landmarks cv2.rectangle(face_frame,(shape[54][0], shape[29][1]), #draw rectangle on right and left cheeks (shape[12][0],shape[33][1]), (0,255,0), 0) cv2.rectangle(face_frame, (shape[4][0], shape[29][1]), (shape[48][0],shape[33][1]), (0,255,0), 0) ROI1 = face_frame[shape[29][1]:shape[33][1], #right cheek shape[54][0]:shape[12][0]] ROI2 = face_frame[shape[29][1]:shape[33][1], #left cheek shape[4][0]:shape[48][0]] # ROI3 = face_frame[shape[29][1]:shape[33][1], #nose # shape[31][0]:shape[35][0]] #get the shape of face for color amplification rshape = np.zeros_like(shape) rshape = self.face_remap(shape) mask = np.zeros((face_frame.shape[0], face_frame.shape[1])) cv2.fillConvexPoly(mask, rshape[0:27], 1) # mask = np.zeros((face_frame.shape[0], face_frame.shape[1],3),np.uint8) # cv2.fillConvexPoly(mask, shape, 1) #cv2.imshow("face align", face_frame) # cv2.rectangle(frame,(shape[54][0], shape[29][1]), #draw rectangle on right and left cheeks # (shape[12][0],shape[54][1]), (0,255,0), 0) # cv2.rectangle(frame, (shape[4][0], shape[29][1]), # (shape[48][0],shape[48][1]), (0,255,0), 0) # ROI1 = frame[shape[29][1]:shape[54][1], #right cheek # shape[54][0]:shape[12][0]] # ROI2 = frame[shape[29][1]:shape[54][1], #left cheek # shape[4][0]:shape[48][0]] else: cv2.putText(frame, "No face detected", (200,200), cv2.FONT_HERSHEY_PLAIN, 1.5, (0, 0, 255),2) status = False return frame, face_frame, ROI1, ROI2, status, mask, face_region # some points in the facial landmarks need to be re-ordered def face_remap(self,shape): remapped_image = shape.copy() # left eye brow remapped_image[17] = shape[26] remapped_image[18] = shape[25] remapped_image[19] = shape[24] remapped_image[20] = shape[23] remapped_image[21] = shape[22] # right eye brow remapped_image[22] = shape[21] remapped_image[23] = shape[20] remapped_image[24] = shape[19] remapped_image[25] = shape[18] remapped_image[26] = shape[17] # neatening remapped_image[27] = shape[0] remapped_image = cv2.convexHull(shape) return remapped_image