基于dlib68点人脸检测的小功能实现
图像旋转找的现成的方法,稍稍麻烦点的地方就是mask处理,虽然目的达到了,但是效果一般
1 import numpy as np 2 import cv2 as cv 3 import dlib 4 import math 5 6 # 做一个戴眼镜的滤镜效果 7 8 detector = dlib.get_frontal_face_detector() 9 predictor = dlib.shape_predictor('dlib/shape_predictor_68_face_landmarks.dat') 10 11 12 # 图像旋转,保持原来大小 13 def rotate_bound(image, angle): 14 # grab the dimensions of the image and then determine the 15 # center 16 (h, w) = image.shape[:2] 17 (cX, cY) = (w // 2, h // 2) 18 19 # grab the rotation matrix (applying the negative of the 20 # angle to rotate clockwise), then grab the sine and cosine 21 # (i.e., the rotation components of the matrix) 22 M = cv.getRotationMatrix2D((cX, cY), -angle, 1.0) 23 cos = np.abs(M[0, 0]) 24 sin = np.abs(M[0, 1]) 25 26 # compute the new bounding dimensions of the image 27 nW = int((h * sin) + (w * cos)) 28 nH = int((h * cos) + (w * sin)) 29 30 # adjust the rotation matrix to take into account translation 31 M[0, 2] += (nW / 2) - cX 32 M[1, 2] += (nH / 2) - cY 33 34 # perform the actual rotation and return the image 35 return cv.warpAffine(image, M, (nW, nH)) 36 37 38 def detect_face(camera_idx): 39 # camera_idx: 电脑自带摄像头或者usb摄像头 40 cv.namedWindow('detect') 41 cap = cv.VideoCapture(camera_idx) 42 43 while cap.isOpened(): 44 cv.namedWindow('detect', cv.WINDOW_AUTOSIZE) 45 ok, frame = cap.read() 46 # 为摄像头的时候,翻转画面 47 if camera_idx == 0 or camera_idx == 1: 48 frame = cv.flip(frame, 1, dst=None) 49 if not ok: 50 break 51 gray = cv.cvtColor(frame, cv.COLOR_BGR2GRAY) 52 rects = detector(gray, 0) 53 for i in range(len(rects)): 54 landmarks = np.matrix([[p.x, p.y] for p in predictor(frame, rects[i]).parts()]) 55 # 脸轮廓:1~17 56 # 眉毛:18~22, 23~27 57 # 鼻梁:28~31 58 # 鼻子:31~36 59 # 眼睛:37~42, 43~48 60 # 嘴唇:49~68 61 # 左眼角和右眼角的位置 62 pos_left = (landmarks[0][0, 0], landmarks[36][0, 1]) 63 pos_right = (landmarks[16][0, 0], landmarks[45][0, 1]) 64 face_center = (landmarks[27][0, 0], landmarks[27][0, 1]) 65 src = cv.imread('images/glasses.jpg') 66 # 433x187眼镜图片原始大小,按人脸比例缩放一下 67 length = pos_right[0] - pos_left[0] 68 width = int(187/(433/length)) 69 src = cv.resize(src, (length, width), interpolation=cv.INTER_CUBIC) 70 71 # 角度旋转,通过计算两个眼角和水平方向的夹角来旋转眼镜 72 sx = landmarks[36][0, 0] - landmarks[45][0, 0] 73 sy = landmarks[36][0, 1] - landmarks[45][0, 1] 74 # 夹角正切值 75 r = sy/sx 76 # 求正切角,弧度转为度 77 degree = math.degrees(math.atan(r)) 78 # 调用旋转方法 79 src = rotate_bound(src, degree) 80 81 # mask处理,去掉旋转后的无关区域,初始化一个全0mask,用或运算处理mask 82 src_mask = np.zeros(src.shape, src.dtype) 83 src_mask = cv.bitwise_or(src, src_mask) 84 # 泊松融合 85 output = cv.seamlessClone(src, frame, src_mask, face_center, cv.MIXED_CLONE) 86 cv.imshow('detect', output) 87 c = cv.waitKey(10) 88 if c & 0xFF == ord('q'): 89 break 90 cap.release() 91 cv.destroyAllWindows() 92 93 94 if __name__ == '__main__': 95 video = 'video/face.mp4' 96 detect_face(video)
眼镜图片
效果
泊松融合三种参数效果在这里一样
除了眼镜图片较浅其他的还算可以吧
还可以扩展面部其他装饰
参考: