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
| class MultiFeatureExtractor: """ 多特征提取器 提取: 1. 眼部:PERCLOS、眨眼频率 2. 嘴部:打哈欠频率 3. 头部:点头/摇头频率 """ def __init__(self): self.face_detector = self._load_mtcnn() def extract_features(self, frame): """ 从单帧提取多部位图像 Returns: eye_img: (3, 64, 64) mouth_img: (3, 64, 64) head_img: (3, 224, 224) """ boxes, landmarks = self.face_detector.detect(frame) if boxes is None: return None, None, None left_eye = landmarks[0] right_eye = landmarks[1] mouth = landmarks[3] eye_img = self._crop_eyes(frame, left_eye, right_eye) mouth_img = self._crop_mouth(frame, mouth) head_img = self._crop_head(frame, boxes[0]) return eye_img, mouth_img, head_img def _crop_eyes(self, frame, left_eye, right_eye): """裁剪双眼区域""" x1 = int(min(left_eye[0], right_eye[0]) - 20) y1 = int(min(left_eye[1], right_eye[1]) - 15) x2 = int(max(left_eye[0], right_eye[0]) + 20) y2 = int(max(left_eye[1], right_eye[1]) + 15) crop = frame[y1:y2, x1:x2] crop = cv2.resize(crop, (64, 32)) padded = np.zeros((64, 64, 3), dtype=np.uint8) padded[16:48, :, :] = crop return padded def _crop_mouth(self, frame, mouth_center): """裁剪嘴部区域""" x, y = mouth_center crop = frame[int(y-20):int(y+20), int(x-30):int(x+30)] crop = cv2.resize(crop, (64, 64)) return crop
|