AI备忘录 - 人脸识别
type: channel
link: https://www.aiuai.cn/category/face/
description: 人脸识别，人脸检测，人脸关键点，人脸对比
items: Dlib库 - 人脸关键点检测与对齐实现
items: 基于OpenCV和dlib的人脸性别及年龄检测的实现
items: 基于OpenCV和 dlib 的眨眼检测Python实现[译]
items: 使用OpenCV和dlib进行人脸姿态估计(python)[转]
items: 人脸头部姿态估计的 Python 实现[转]
items: 基于OpenCV和Dlib的头部姿态估计[译]
items: Github 项目 - FaceBoxes高精度实时人脸检测器
items: Dlib 库 - 人脸检测及人脸关键点检测

Dlib库 - 人脸关键点检测与对齐实现
type: item
date: 2020-11-19T20:20:00+08:00
description: 在 StyleGAN2 中，可以采用基于 Dlib 库实现人脸关键点检测、人脸对齐.1. 人脸关键点检测import dlib #predictor_model_path='http://dlib.net/files/shape_predictor_68_face_landmarks.dat.bz2' class LandmarksDetector: def __init__(self, predictor_model_path): """ :param predictor_model_path: path to shape_predictor_68_face_landmarks.dat file """ self.detector = dlib.get_frontal_face_detector() # cnn_face_detection_model_v1 also can be used self.shape_predictor = dlib.shape_predictor(predictor_model_path) def get_landmarks(self, image): img = dlib.load_rgb_image(image) dets = self.detector(img, 1) for detection in dets: try: face_landmarks = [(item.x, item.y) for item in self.shape_predictor(img, detection).parts()] yield face_landmarks except: print("Exception in get_landmarks()!")2. 人脸对齐import numpy as np import scipy.ndimage import os import PIL.Image def image_align(src_file, dst_file, face_landmarks, output_size=1024, transform_size=4096, enable_padding=True, x_scale=1, y_scale=1, em_scale=0.1, alpha=False): # Align function from FFHQ dataset pre-processing step # https://github.com/NVlabs/ffhq-dataset/blob/master/download_ffhq.py lm = np.array(face_landmarks) lm_chin = lm[0 : 17] # left-right lm_eyebrow_left = lm[17 : 22] # left-right lm_eyebrow_right = lm[22 : 27] # left-right lm_nose = lm[27 : 31] # top-down lm_nostrils = lm[31 : 36] # top-down lm_eye_left = lm[36 : 42] # left-clockwise lm_eye_right = lm[42 : 48] # left-clockwise lm_mouth_outer = lm[48 : 60] # left-clockwise lm_mouth_inner = lm[60 : 68] # left-clockwise # Calculate auxiliary vectors. eye_left = np.mean(lm_eye_left, axis=0) eye_right = np.mean(lm_eye_right, axis=0) eye_avg = (eye_left + eye_right) * 0.5 eye_to_eye = eye_right - eye_left mouth_left = lm_mouth_outer[0] mouth_right = lm_mouth_outer[6] mouth_avg = (mouth_left + mouth_right) * 0.5 eye_to_mouth = mouth_avg - eye_avg # Choose oriented crop rectangle. x = eye_to_eye - np.flipud(eye_to_mouth) * [-1, 1] x /= np.hypot(*x) x *= max(np.hypot(*eye_to_eye) * 2.0, np.hypot(*eye_to_m…

基于OpenCV和dlib的人脸性别及年龄检测的实现
type: item
date: 2019-03-13T22:01:00+08:00
description: 采用 OpenCV DNN 模块实现的人脸性别及年龄检测，整个项目比较简单、清晰明了，过程主要包括：[1] - 检测图片中的人脸框(如，采用 dlib 库).[2] - 检测人脸的性别和年龄.[3] - 检测结果可视化.1. 相关模型所采用的模型分别如下：[1] - 人脸框检测模型这里采用了 dlib 的 CNN 人脸框检测模型：mmod_human_face_detector.dat.bz2或者，OpenCV DNN 模块自带的残差网络的人脸检测模型：opencv_face_detector.pbtxtopencv_face_detector_uint8.pb[2] - 性别检测模型(Caffe)：gender_deploy.prototxtgender_net.caffemodel性别共两类：Male，Female[3] - 年龄预测模型(Caffe)：age_deploy.prototxtage_net.caffemodel年龄共八类：(0-2), (4-6), (8-12), (15-20), (25-32), (38-43), (48-53), (60-100)2. 具体实现#!--*-- coding:utf-8 --*-- import os import cv2 import time import matplotlib.pyplot as plt import dlib class AgeGenderDetector(): def __init__(self): # Load model and networks # Age self.ageList = ['(0-2)', '(4-6)', '(8-12)', '(15-20)', '(25-32)', '(38-43)', '(48-53)', '(60-100)'] ageProto = "age_deploy.prototxt" ageModel = "age_net.caffemodel" self.ageNet = cv2.dnn.readNet(ageModel, ageProto) # Gender self.genderList = ['Male', 'Female'] genderProto = "gender_deploy.prototxt" genderModel = "gender_net.caffemodel" self.genderNet = cv2.dnn.readNet(genderModel, genderProto) # Face detection - OpenCV DNN faceProto = "opencv_face_detector.pbtxt" faceModel = "opencv_face_detector_uint8.pb" self.faceNet = cv2.dnn.readNet(faceModel, faceProto) # Face detection - dlib dlib_cnn_face_model = "mmod_human_face_detector.dat" self.dlib_cnn_face_detector = dlib.cnn_face_detection_model_v1(dlib_cnn_face_model) self.mean_values = (78.4263377603, 87.7689143744, 114.895847746) self.padding = 20 def dlib_cnn_face_detect(self, img): detections = self.dlib_cnn_face_detector(img, 1) bboxes = [] if len(detections) > 0: for i, d in enumerate(detections): x1 = d.rect.left() y1 = d.rect.top() x2 = d.rect.right() y2 = d.rect.bottom() bboxes.append([x1, y1, x2, y2]) # return bboxes def opencv_dnn_face_detect(self, img_cv2, conf_threshold=0.7): height, width, _ = img_cv2.shape blob = cv2.dnn.blobFromImage(img_cv2, 1.0, (300, 300), [104, 117, 123], True, False) self.faceNet.setInput(blob) detections = sel…

基于OpenCV和 dlib 的眨眼检测Python实现[译]
type: item
date: 2019-02-28T10:50:00+08:00
description: 1. 基于 OpenCV 和 dlib 的实时人脸特征点检测原文：Detect eyes, nose, lips, and jaw with dlib, OpenCV, and Python - 2017.04.10原文：Real-time facial landmark detection with OpenCV, Python, and dlib - 2017.04.17作者：Adrian Rosebrock安装 imutils 和 dlib：pip install dlib pip install imutils #或 pip install --upgrade imutilsdlib 库检测的人脸特征点如图：以视频流人脸特征点检测为例 - video_facial_landmarks.py:from imutils.video import VideoStream from imutils import face_utils import datetime import argparse import imutils import time import dlib import cv2 # construct the argument parse and parse the arguments ap = argparse.ArgumentParser() ap.add_argument("-p", "--shape-predictor", required=True, help="path to facial landmark predictor") ap.add_argument("-r", "--picamera", type=int, default=-1, help="whether or not the Raspberry Pi camera should be used") args = vars(ap.parse_args()) # initialize dlib's face detector (HOG-based) and then create # the facial landmark predictor print("[INFO] loading facial landmark predictor...") detector = dlib.get_frontal_face_detector() predictor = dlib.shape_predictor(args["shape_predictor"]) # initialize the video stream and allow the cammera sensor to warmup print("[INFO] camera sensor warming up...") vs = VideoStream(usePiCamera=args["picamera"] > 0).start() time.sleep(2.0) # loop over the frames from the video stream while True: # grab the frame from the threaded video stream, resize it to # have a maximum width of 400 pixels, and convert it to # grayscale frame = vs.read() frame = imutils.resize(frame, width=400) gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY) # detect faces in the grayscale frame rects = detector(gray, 0) # import the necessary packages from imutils.video import VideoStream from imutils import face_utils import datetime import argparse import imutils import time import dlib import cv2 # construct the argument parse and parse the arguments ap = argparse.ArgumentParser() ap.add_argument("-p", "--shape-predictor", required=True, help="path to facial landmark predictor…

使用OpenCV和dlib进行人脸姿态估计(python)[转]
type: item
date: 2019-02-27T22:26:00+08:00
description: 原文：使用opencv和dlib进行人脸姿态估计(python) - 2018.09.18作者：yuanlulu - CSDN在计算机视觉中，物体的姿态是指相对于相机的相对取向和位置。本文主要参考了 Head Pose Estimation using OpenCV and Dlib - 2016.09.26.人脸姿态估计的目的就是获取人脸相对相机的朝向.人脸姿态估计的思想：旋转三维标准模型一定角度，直到模型上“三维特征点”的“2维投影”，与待测试图像上的特征点（图像上的特征点显然是2维）尽量重合.基于OpenCV和Dlib的头部姿态估计 - AIUAIPython 实现：#!/usr/bin/env python3 import cv2 import numpy as np import dlib import time import math detector = dlib.get_frontal_face_detector() predictor = dlib.shape_predictor("shape_predictor_68_face_landmarks.dat") POINTS_NUM_LANDMARK = 68 # 获取最大的人脸 def _largest_face(dets): if len(dets) == 1: return 0 face_areas = [(det.right()-det.left())*(det.bottom()-det.top()) for det in dets] largest_area = face_areas[0] largest_index = 0 for index in range(1, len(dets)): if face_areas[index] > largest_area : largest_index = index largest_area = face_areas[index] print("largest_face index is {} in {} faces".format(largest_index, len(dets))) return largest_index # 从dlib的检测结果抽取姿态估计需要的点坐标 def get_image_points_from_landmark_shape(landmark_shape): if landmark_shape.num_parts != POINTS_NUM_LANDMARK: print("ERROR:landmark_shape.num_parts-{}".format(landmark_shape.num_parts)) return -1, None # 2D image points. # If you change the image, you need to change vector image_points = np.array([ (landmark_shape.part(30).x, landmark_shape.part(30).y), # Nose tip (landmark_shape.part(8).x, landmark_shape.part(8).y), # Chin (landmark_shape.part(36).x, landmark_shape.part(36).y), # Left eye left corner (landmark_shape.part(45).x, landmark_shape.part(45).y), # Right eye right corne (landmark_shape.part(48).x, landmark_shape.part(48).y), # Left Mouth corner (landmark_shape.part(54).x, landmark_shape.part(54).y) # Right mouth corner ], dtype="double") return 0, image_points # 用dlib检测关键点，返回姿态估计需要的几个点坐标 def get_image_points(img): #gray = cv2.cvtColor( img, cv2.COLOR_BGR2GRAY ) # 图片调整为灰色 dets = detector( img, 0 ) if 0 == len( dets ): print( "ERROR: found no face" ) return -1, None largest_index = _largest_face(dets) face_recta…

人脸头部姿态估计的 Python 实现[转]
type: item
date: 2019-02-27T16:18:00+08:00
description: 原文1 - 利用二维图像进行头部姿态估计 - 2017.10.23原文2 - 人脸姿态估计 - 2018.04.17坐标变换：利用世界坐标系旋转、平移矩阵，将 3D点 从世界坐标系变换到相机坐标系中. 即：通过算法完成世界坐标系(3D)、2D landmark输入image、相机坐标系之间的映射转换和标定.2D人脸特征点与3D世界坐标系的对应点1. 计算旋转矩阵和平移矩阵[基于OpenCV和Dlib的头部姿态估计[译] - AIUAI](https://www.aiuai.cn/aifarm909.html) - 10.2 Python 实现.2. 旋转矩阵转换为欧拉角Yaw:摇头 左正右负Pitch:点头 上负下正Roll:摆头（歪头）左负 右正// C++ static cv::Vec3d RotationMatrix2Euler(const cv::Matx33d& rotation_matrix) { double q0 = sqrt(1 + rotation_matrix(0, 0) + rotation_matrix(1, 1) + rotation_matrix(2, 2)) / 2.0; double q1 = (rotation_matrix(2, 1) - rotation_matrix(1, 2)) / (4.0*q0); double q2 = (rotation_matrix(0, 2) - rotation_matrix(2, 0)) / (4.0*q0); double q3 = (rotation_matrix(1, 0) - rotation_matrix(0, 1)) / (4.0*q0); double t1 = 2.0 * (q0*q2 + q1*q3); double yaw = asin(2.0 * (q0*q2 + q1*q3)); double pitch = atan2(2.0 * (q0*q1 - q2*q3), q0*q0 - q1*q1 - q2*q2 + q3*q3); double roll = atan2(2.0 * (q0*q3 - q1*q2), q0*q0 + q1*q1 - q2*q2 - q3*q3); return cv::Vec3d(pitch, yaw, roll); }% matlab function [euler] = Rot2Euler(R) q0 = sqrt( 1 + R(1,1) + R(2,2) + R(3,3) ) / 2; q1 = (R(3,2) - R(2,3)) / (4*q0) ; q2 = (R(1,3) - R(3,1)) / (4*q0) ; q3 = (R(2,1) - R(1,2)) / (4*q0) ; yaw = asin(2*(q0*q2 + q1*q3)); pitch= atan2(2*(q0*q1-q2*q3), q0*q0-q1*q1-q2*q2+q3*q3); roll = atan2(2*(q0*q3-q1*q2), q0*q0+q1*q1-q2*q2-q3*q3); euler = [pitch, yaw, roll];Python 实现：# Python class PnpHeadPoseEstimator: """ 基于 OpenCV PnP 算法实现的头部姿态估计. It finds Roll, Pitch and Yaw of the head given a figure as input. It uses the PnP algorithm and it requires the dlib library """ def __init__(self, cam_w, cam_h, dlib_shape_predictor_file_path): """ @param cam_w the camera width. If you are using a 640x480 resolution it is 640 @param cam_h the camera height. If you are using a 640x480 resolution it is 480 @dlib_shape_predictor_file_path path to the dlib file for shape prediction (dlib/shape_predictor_68_face_landmarks.dat) """ if(IS_DLIB_INSTALLED == False): raise ValueError('[DEEPGAZE] PnpHeadPoseEstimator: the dl…

基于OpenCV和Dlib的头部姿态估计[译]
type: item
date: 2019-02-27T14:57:00+08:00
description: 原文：Head Pose Estimation using OpenCV and Dlib - 2016.09.26主要介绍如何采用 OpenCV 和 Dlib 库，实现图片中人头部姿态估计.在很多场景中，需要知道人头部相对于相机的倾斜程度. 例如，在 VR 领域，可以采用头部姿态来渲染场景的视角. 在辅助驾驶系统中，对准司机脸部的相机，可以根据头部姿态估计，判断司机是否注意力集中. 此外，还可以采用给予手势的头部姿态来控制 hands-free 应用(或游戏). 例如，将头部从左到有扭转，可以表示 NO. 但，如果是在印度南部，这个信号表示 YES.本文作者认为，头部姿态估计是很有应用价值的.1. 什么是姿态估计？在 CV 领域中，物体的姿态是其相对于相机的方向(orientation)和位置(position). 通过移动物体相对于相机的位置，或者移动相机相对于物体的位置，即可改变物体的姿态.这里所描述的姿态估计问题通常是 Perspective-n-Point (PNP) 问题，其旨在，对于标定相机(calibrated camera)，找出物体的姿态；其中，已知物体的 n 个 3D 点，以及其在图片中所对应的 2D 投影.对于一个标定好的摄像机，根据目标在 3D 世界坐标系中 n 个点的坐标和对应投影到 2D 图像坐标系中的点集之间的变换关系矩阵进行求解.2. 相机运动(camera motion) 的数学描述3D 刚体仅有两种相对于相机的运动：[1] - 平移将相机从其当前 3D 位置 $(X, Y, Z)$ 移动到新的 3D 位置 $(X', Y', Z')$，即为 平移. 易知，其有 3 个自由度(degrees of freedom)，可以分别在 X, Y 或 Z 方向进行评议.平移可以表示为向量：$\mathbf{t} = (X'-X, Y'-Y, Z'-Z)$.[2] - 旋转关于 X, Y 和 Z 轴，旋转相机. 因此，旋转 也有三个自由度. 旋转有很多种表示方式，可以是欧拉角(Euler angles) (roll,pitch,yaw) 或者，3x3 旋转矩阵(rotation matrix)，或者旋转和角度的方向(direction of rotation (i.e. axis ) and angle).因此，3D 物体的姿态估计，即是计算 6 个变量 - 三个平移和三个旋转.3. 姿态估计所需信息为了计算图片中物体的 3D 姿态，需要知道一下信息：[1] - 一些点的 2D 坐标位置图片中一些点的 2D 坐标 (x, y).对于人脸而言，往往选择眼角(corners of the eyes), 鼻尖(tip of the nose), 嘴角(corners of the mouth) 等位置的点. Dlib 库的 人脸关键点检测 可以定位很多人脸关键点.这里采用的人脸关键点有：鼻尖，下巴，左眼的左角，右眼的右角，左嘴角，右嘴角.[2] - 同一批点的 3D 位置同时还需要 2D 特征点对应的 3D 位置. 可能首先会想到，需要获取图片中人体的 3D 模型，才能得到 3D 位置. 而，实际上，是不需要的. 通用 3D 模型即可.如何获取头部的 3D 模型呢？ 实际上不需要 完整的 3D 模型，只需要任意坐标系中一些点的 3D 位置. 这里采用如下的 3D 点：(1) - 鼻尖：( 0.0, 0.0, 0.0)(2) - 下巴：( 0.0, -330.0, -65.0)(3) - 左眼左角：(-225.0f, 170.0f, -135.0)(4) - 右眼右角：( 225.0, 170.0, -135.0)(5) - 左嘴角：(-150.0, -150.0, -125.0)(6) - 右嘴角：(150.0, -150.0, -125.0)要注意的是，这些点是在任意坐标系统的. 即世界坐标系(World Coordinates).[3] - 相机的内在参数(intrinsic parameters)正如上面所述，这里需要首先进行相机标定的(calibrated). 即，需要知道相机的焦距(focal length)，图像的光学中心(optical center)和径向畸变参数(radial distortion parameters).由于不是采用精度 3D 模型来逼近问题，可以采用图片中心(image center)来逼近光学中心(optical center)，采用图像的宽度(像素值)来逼近焦距(focal length)，假设径向畸变(radial disortion) 不存在的话.进行相机参数估计时首先需要对相机进行标定，精确的相机标定需要使用张正友的棋盘格标定，这里还是进行近似. 相机的内参数矩…

Github 项目 - FaceBoxes高精度实时人脸检测器
type: item
date: 2019-02-25T22:02:00+08:00
description: 主页： 智云视图FaceBoxes 完整复现. 论文： FaceBoxes: A CPU Real-time Face Detector with High Accuracy - 2018论文源码：1. FaceBoxes 测试Caffemodel - FaceBoxes_1024x1024.caffemodel (3.6M)Prototxt - faceboxes_deploy.prototxtCaffe - [caffe-ssd]()# -*- coding: utf-8 -* import numpy as np import matplotlib.pyplot as plt import sys,os import cv2 caffe_root = '/path/to/caffe-ssd/' sys.path.insert(0, caffe_root + 'python') import caffe import time net_file= 'faceboxes_deploy.prototxt' caffe_model='FaceBoxes_1024x1024.caffemodel' caffe.set_mode_cpu() # cpu # caffe.set_mode_gpu() # gpu net = caffe.Net(net_file,caffe_model,caffe.TEST) CLASSES = ('background', 'face') transformer = caffe.io.Transformer({'data': net.blobs['data'].data.shape}) transformer.set_transpose('data', (2, 0, 1)) transformer.set_mean('data', np.array([104, 117, 123])) # mean pixel def preprocess(src): img = cv2.resize(src, (1024,1024)) img = img - 127.5 img = img * 0.007843 return img def postprocess(img, out): h = img.shape[0] w = img.shape[1] box = out['detection_out'][0,0,:,3:7] * np.array([w, h, w, h]) cls = out['detection_out'][0,0,:,1] conf = out['detection_out'][0,0,:,2] return (box.astype(np.int32), conf, cls) def detect(imgfile): origimg = cv2.imread(imgfile) transformed_image = transformer.preprocess('data', origimg) net.blobs['data'].data[...] = transformed_image time_start = time.time() out = net.forward() print("[INFO]timecost: ", time.time() - time_start) box, conf, cls = postprocess(origimg, out) for i in range(len(box)): p1 = (box[i][0], box[i][1]) p2 = (box[i][2], box[i][3]) cv2.rectangle(origimg, p1, p2, (0, 255, 0)) p3 = (max(p1[0], 15), max(p1[1], 15)) title = "%s:%.2f" % (CLASSES[int(cls[i])], conf[i]) cv2.putText(origimg, title, p3, cv2.FONT_ITALIC, 0.6, (0, 255, 0), 1) plt.imshow(origimg[:,:,::-1]) plt.axis("off") plt.show() return True if __name__ == '__main__': test_dir = "/path/to/images" for img_name in os.listdir(test_dir): img_file = os.path.join(test_dir, img_name) result = detect(img_file) print(…

Dlib 库 - 人脸检测及人脸关键点检测
type: item
date: 2019-02-23T13:45:00+08:00
description: Dlib 官网 - Dlib C++ LibraryDlib - GithubDlib 是一个十分优秀好用的机器学习库，其源码均由 C++ 实现，并提供了 Python 接口，可广泛适用于很多场景.这里主要记录 Dlib 中关于人脸检测和人脸关键点等技术的 python 应用.pip 安装：sudo apt-get install cmake sudo pip install dlib或 Github 源码安装.1. 人脸检测 Face Detector人脸检测，是检测出图片中包含的正面人脸.1.1. 基于 HOG 特征和线性分类器的人脸检测下面是采用经典的 HOG(Histogram of Oriented Gradients) 特征 结合线性分类器、图像金字塔(image pyramid) 及滑窗检测机制(sliding window detection scheme)实现的人脸检测器.#!/usr/bin/python # -*- coding: utf-8 -*- import sys import dlib detector = dlib.get_frontal_face_detector() def face_detect(imgfile): win = dlib.image_window() print("Processing file: {}".format(imgfile)) img = dlib.load_rgb_image(imgfile) # 人脸检测 dets = detector(img, 1) # len(dets) 即为检测到的人脸个数 print("Number of faces detected: {}".format(len(dets))) # 遍历所有检测到人脸的坐标 # left：人脸左边距离图片左边界的距离 # right：人脸右边距离图片左边界的距离 # top：人脸上边距离图片上边界的距离 # bottom：人脸下边距离图片上边界的距离 for i, d in enumerate(dets): print("Detection {}: Left: {} Top: {} Right: {} Bottom: {}".format( i, d.left(), d.top(), d.right(), d.bottom())) win.clear_overlay() win.set_image(img) win.add_overlay(dets) dlib.hit_enter_to_continue() def face_detect_with_scores(imgfile): win = dlib.image_window() # 如果要进一步得到更全面的检测信息，如每个检测结果的分数(score). # score 值越大，则检测的可信度越高. img = dlib.load_rgb_image(imgfile) # 第三个参数 -1 用于设置调整检测阈值； # 如果该参数值为负数，则返回更多的结果； # 如果该参数值为正数，则返回较少的结果. dets, scores, idx = detector.run(img, 1, -1) for i, d in enumerate(dets): print("Detection {}, score: {}, face_type:{}".format( d, scores[i], idx[i])) win.clear_overlay() win.set_image(img) win.add_overlay(dets) dlib.hit_enter_to_continue() if __name__ == '__main__': imgfile = "test.jpg" face_detect(imgfile) face_detect_with_scores(imgfile)1.2. 基于 CNN 的人脸检测采用预训练的 CNN 模型进行图片中的人脸检测.基于 CNN 模型比基于 HOG 特征模型的人脸检测准确度更高. 但是需要更多的计算资源，即在 GPU 上运行才可有较好的运行速率.预训练模型：http://dlib.net/files/mmod_human_face_detector.dat.bz2#!/usr/bin/python # -*- coding: utf-8 -*- import sys import dlib # 加载预训练人脸检测CNN模型 cnn_face_model = "mmod_human_face_detector.dat" cnn_face_detector = dlib.cnn_face_detection_…